Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Robust ServerSocket not throw (EOL) on recoverable accept failure #10386

Merged
merged 2 commits into from
Nov 13, 2024

Conversation

sgothel
Copy link

@sgothel sgothel commented Oct 31, 2024

  • Resolves: ...
  • Target version: master

Summary

  • ServerSocket shall not throw (EOL) on accept returning nullptr
  • Simplify accept, ending application on unrecoverable error

Have ServerSocket::accept determine whether to Util::forcedExit(EX_SOFTWARE)
on unrecoverable errors:

  • Exit application if ::accept returns an unrecoverable errno (see below)
    • tolerate Socket ctor exceptions
    • tolerate ::accept recoverable errors (see below)
  • Note, the following are no throw
    • ::close
    • ::inet_ntop

Also reject exceeding external connections right within ServerSocket::accept,
avoiding creation of Socket objects - hence saving resources.

Recoverable ::accept errno values
following accept(2) are

  • EAGAIN // == EWOULDBLOCK
  • ENETDOWN // man accept(2): to be treated like EAGAIN
  • EPROTO // man accept(2): to be treated like EAGAIN
  • ENOPROTOOPT // man accept(2): to be treated like EAGAIN
  • EHOSTDOWN // man accept(2): to be treated like EAGAIN
  • ENONET // man accept(2): to be treated like EAGAIN (undef on BSD, Apple, ..)
  • EHOSTUNREACH // man accept(2): to be treated like EAGAIN
  • EOPNOTSUPP // man accept(2): to be treated like EAGAIN
  • ENETUNREACH // man accept(2): to be treated like EAGAIN
  • ECONNABORTED // OK
  • ETIMEDOUT // OK, should not happen due ppoll

May consider handling temporary EMFILE, ENFILE, ENOBUFS and ENOMEM errors?

Unit Testing

Unit testing hooks for failure injection is provided via

  • UnitWSD::simulateExternalAcceptError()
  • UnitWSD::simulateExternalSocketCtorException()

and utilized in

  • test/UnitServerSocketAcceptFailure1.cpp
  • test/UnitStreamSocketCtorFailure1.cpp

Checklist

  • I have run make prettier-write and formatted the code.
  • All commits have Change-Id
  • I have run tests with make check
  • I have issued make run and manually verified that everything looks okay
  • Documentation (manuals or wiki) has been updated or is not required

Copy link
Contributor

@mmeeks mmeeks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the connection counting code is now looking good.
Getting it in is blocked by a) CI - and b) now fixing up the ServerSocket change here to make it much smaller and more helpful I think.
Thanks.

net/ServerSocket.hpp Outdated Show resolved Hide resolved
net/ServerSocket.hpp Outdated Show resolved Hide resolved
net/ServerSocket.hpp Outdated Show resolved Hide resolved
net/Socket.cpp Outdated Show resolved Hide resolved
net/Socket.cpp Show resolved Hide resolved
net/Socket.cpp Outdated Show resolved Hide resolved
net/Socket.cpp Outdated Show resolved Hide resolved
@sgothel sgothel force-pushed the private/sgothel/sockrepair4_p2 branch from 974b9a9 to 44f01da Compare October 31, 2024 18:22
@sgothel
Copy link
Author

sgothel commented Oct 31, 2024

This is the ServerSocket fix vanilla branch w/o merged max-connection
https://github.com/CollaboraOnline/online/tree/private/sgothel/sockrepair4_p1

This is the ServerSocket fix branch w/ merged max-connection (this reviewed one)
https://github.com/CollaboraOnline/online/tree/private/sgothel/sockrepair4_p2

I applied all review remarks .. but not fully removed the 'swizzle around' lines
for clarity of the resulting code, please see
https://github.com/CollaboraOnline/online/blob/private/sgothel/sockrepair4_p2/net/Socket.cpp#L1153

@sgothel sgothel force-pushed the private/sgothel/sockrepair4_p2 branch from 44f01da to 641a07d Compare November 1, 2024 10:38
@sgothel sgothel changed the title Implement MaxConnection Limit (2c) Robust ServerSocket not throw (EOL) on recoverable accept failure Nov 1, 2024
@sgothel sgothel force-pushed the private/sgothel/sockrepair4_p2 branch 2 times, most recently from a8f061b to b8f548b Compare November 1, 2024 17:48
Copy link
Contributor

@mmeeks mmeeks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see unit tests for this - possibly we need a fault injection hook in UnitBase to throw during SSL socket creation or something - and of course for when we run out of sockets too.
Thanks!

@sgothel sgothel force-pushed the private/sgothel/sockrepair4_p2 branch from b8f548b to 0a29005 Compare November 6, 2024 14:58
@sgothel
Copy link
Author

sgothel commented Nov 6, 2024

I'd like to see unit tests for this - possibly we need a fault injection hook in UnitBase to throw during SSL socket creation or something - and of course for when we run out of sockets too. Thanks!

Revised pull request including unit tests injection

  • recoverable ::accept errors
  • non-recoverable ::accept errors
  • recoverable (server) StreamSocket ctor exceptions

Classification of recoverable ::accept errors has been revised and documented.

@sgothel
Copy link
Author

sgothel commented Nov 6, 2024

Unit test logs w/ error injections

@sgothel sgothel marked this pull request as ready for review November 6, 2024 15:04
@sgothel sgothel requested a review from mmeeks November 6, 2024 15:05
@sgothel sgothel force-pushed the private/sgothel/sockrepair4_p2 branch from 0a29005 to 98ae285 Compare November 6, 2024 15:25
@sgothel sgothel requested a review from caolanm November 6, 2024 15:31
@caolanm
Copy link
Contributor

caolanm commented Nov 6, 2024

ENONET doesn't appear to exist on IOS, presumably an easy fix for that build error

@sgothel sgothel force-pushed the private/sgothel/sockrepair4_p2 branch from 98ae285 to a6a1ab5 Compare November 6, 2024 18:11
@sgothel
Copy link
Author

sgothel commented Nov 6, 2024

ENONET doesn't appear to exist on IOS, presumably an easy fix for that build error

thx, checked on FreeBSD's accept(2) as well as on their errno.h + Apple's. So it was just this one missing on BSD + Apple.

Copy link
Contributor

@mmeeks mmeeks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs some more work; thanks.

net/Socket.cpp Outdated Show resolved Hide resolved
net/Socket.cpp Outdated Show resolved Hide resolved
net/Socket.cpp Outdated Show resolved Hide resolved
net/Socket.cpp Outdated Show resolved Hide resolved
net/Socket.hpp Outdated Show resolved Hide resolved
@sgothel sgothel force-pushed the private/sgothel/sockrepair4_p2 branch 3 times, most recently from 36dad03 to 30a8c40 Compare November 8, 2024 13:24
net/Socket.cpp Outdated Show resolved Hide resolved
@sgothel sgothel force-pushed the private/sgothel/sockrepair4_p2 branch from 30a8c40 to 7fcb554 Compare November 8, 2024 16:19
@sgothel sgothel requested a review from mmeeks November 11, 2024 15:16
commit 94f2825
removed WebSocketHandler's WS Ping timeout functionality and disabled the unit test.

Signed-off-by: Sven Göthel <[email protected]>
Change-Id: I6c8a805437f66346ea3feac421b3a15707e7417f
@caolanm caolanm force-pushed the private/sgothel/sockrepair4_p2 branch from 7fcb554 to 1b5ebe3 Compare November 11, 2024 19:27
Copy link
Contributor

@mmeeks mmeeks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nearly there.

net/Socket.cpp Outdated Show resolved Hide resolved
net/Socket.cpp Outdated Show resolved Hide resolved
net/ServerSocket.hpp Outdated Show resolved Hide resolved
net/Socket.cpp Outdated Show resolved Hide resolved
net/Socket.cpp Show resolved Hide resolved
net/Socket.cpp Outdated Show resolved Hide resolved
@sgothel sgothel force-pushed the private/sgothel/sockrepair4_p2 branch from 1b5ebe3 to 99142ee Compare November 12, 2024 14:22
@sgothel sgothel requested a review from mmeeks November 12, 2024 14:22
Copy link
Contributor

@mmeeks mmeeks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry missed a couple more here; hopefully next round we'll get it in!

net/Socket.cpp Outdated Show resolved Hide resolved
net/Socket.cpp Outdated Show resolved Hide resolved
@mmeeks
Copy link
Contributor

mmeeks commented Nov 12, 2024

Otherwise - much better of course.

@sgothel sgothel force-pushed the private/sgothel/sockrepair4_p2 branch from 99142ee to 82409cc Compare November 13, 2024 08:29
…ify accept.

Have `ServerSocket::accept` determine whether to `Util::forcedExit(EX_SOFTWARE)`
on unrecoverable errors:
- Exit application if `::accept` returns an unrecoverable `errno` (see below)
  - tolerate `Socket` ctor exceptions
  - tolerate `::accept` recoverable errors (see below)
- Note, the following are `no throw`
  - `::close`
  - `::inet_ntop`

Also reject exceeding external connections right within `ServerSocket::accept`,
avoiding creation of `Socket` objects - hence saving resources.

Recoverable `::accept` `errno` values
following [accept(2)](https://www.man7.org/linux/man-pages/man2/accept.2.html) are
- EAGAIN         // == EWOULDBLOCK
- ENETDOWN       // man accept(2): to be treated like EAGAIN
- EPROTO         // man accept(2): to be treated like EAGAIN
- ENOPROTOOPT    // man accept(2): to be treated like EAGAIN
- EHOSTDOWN      // man accept(2): to be treated like EAGAIN
- ENONET         // man accept(2): to be treated like EAGAIN (undef on BSD, Apple, ..)
- EHOSTUNREACH   // man accept(2): to be treated like EAGAIN
- EOPNOTSUPP     // man accept(2): to be treated like EAGAIN
- ENETUNREACH    // man accept(2): to be treated like EAGAIN
- ECONNABORTED   // OK
- ETIMEDOUT      // OK, should not happen due ppoll

We also allow retrying on temporary EMFILE, ENFILE, ENOBUFS and ENOMEM errors,
which may also be candidates for later fine grained control in case of resource degradation.

Unit testing hooks for failure injection is provided via
- UnitWSD::simulateExternalAcceptError()
- UnitWSD::simulateExternalSocketCtorException()

and utilized in
- test/UnitServerSocketAcceptFailure1.cpp
- test/UnitStreamSocketCtorFailure1.cpp

Signed-off-by: Sven Göthel <[email protected]>
Change-Id: I939df8e8462d2c29d19214a9b5fb70ad37dc7500
@sgothel sgothel force-pushed the private/sgothel/sockrepair4_p2 branch from 82409cc to 4dbee2e Compare November 13, 2024 08:31
@sgothel
Copy link
Author

sgothel commented Nov 13, 2024

missed one `amend'

@sgothel sgothel requested a review from mmeeks November 13, 2024 09:50
Copy link
Contributor

@mmeeks mmeeks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lovely thank you - didn't read the unit tests much; but really glad to see them =)

@mmeeks mmeeks merged commit 2fbdc2a into master Nov 13, 2024
13 checks passed
@mmeeks mmeeks deleted the private/sgothel/sockrepair4_p2 branch November 13, 2024 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants