-
-
Notifications
You must be signed in to change notification settings - Fork 361
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
Release all waiting processes when destroying a socket (fixes #15975) #16073
Release all waiting processes when destroying a socket (fixes #15975) #16073
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the changes.
Maybe @tesonep wants to give a quick look?
Otherwise it seems good to me.
@daniels220 could you give us for the record some details about how "hard" have you tested this? Or some scenario you foresee that we need to test a bit more?
Send #signalAll to all three semaphores as part of #destroy so any waiting processes are immediately unblocked. Nil the semaphores first to minimize the possibility of a race condition. Then, improve reporting of this condition by making sure everyone has an #ifClosed: branch--specifically #waitFor{Connection|Accept}For:, analogous to #waitForData/#waitForSendDone families. Leave #waitForDisconnectionFor: alone as returning a boolean, since the socket being destroyed indeed means it is disconnected, so the only failure condition is a timeout. Plus some cleanup of the loops to reduce duplicated code.
…he socket is already destroyed
2189ca6
to
1d7b1e9
Compare
there is a seemingly related issue in the ci, ideas ?
|
To be honest, not as hard as I/we probably should, but at the same time I can't put a finger on why. There are just so many different ways to use sockets, and this was driven by finding that a pattern in the code I work with just doesn't work, but I'm always wary when touching code this central to something. (A little background: I work on a large legacy application being ported to Pharo, and it uses a long-lived socket connection, which has processes waiting on it for data to arrive. In other dialects we found that the most reliable way to close the connection and release those processes was to close the socket "out from under them", rather than explicitly terminate them—trying that would sometimes confuse the FFI layer and cause an image crash, where closing the socket would raise an "error" on the C library side which would cleanly propagate and unwind the FFI call. Jump on over to Pharo, and I find that tests are failing because the connection just never tears down properly as far as the test is concerned (it's checking both the socket and the processes, since it's important that they do wind down so they can be started back up again with a new socket later).) I find it a bit strange TBH that closing the socket doesn't cause the semaphores to be signaled by the SocketPlugin code—surely closing a socket causes an active Re: the CI failure—I notice that Lemme sleep on this a bit and see what I think about those two points, and/or if I think of ways to better test it. I notice |
Haha, actually my question was not to block the issue here but to document it. I know that it's not easy to test/measure the impact of this fix. But I'm glad you have it in mind. Just FTR, if you think of some tests in the future, I'd like to see them :) |
Argh, I missed that this was breaking the CI because of a missing |
Yes, I saw that |
Yes, it makes sense to me.
To me here the extension is adding a missing Semaphore functionality...
This is a third solution (which would be similar to pushing the Socket >> signalAll: semaphore
...
And yes, if actually we are using semaphores as mutexes, maybe a single Do you want that I revert the revert to continue working on this? |
Hi @daniels220 any news on this front? How do you want that we proceed? |
I've just been busy the past week, thanks for the reminder. Hmm...I had some concerns about introducing In this particular case, the "ideal" method would be a So, I've resubmitted #16172, which includes the reapply as the first commit before tweaking things. I hope that's convenient for you? |
Oh, sorry, no intention to bother you, just I needed info to move on.
I undertand
I agree with both your feeling and your final analysis ^^
I like this idea! I'd make it part of another issue though.
Yes, this is good as it allows us to move on!
It's great! thanks! I'll pass over it between today and tomorrow! |
Can you tell us more (if possible)? Maybe a new story you could describe for https://pharo.org/success ? |
Send #signalAll to all three semaphores as part of #destroy so any waiting processes are immediately unblocked. Nil the semaphores first to minimize the possibility of a race condition.
Then, improve reporting of this condition by making sure everyone has an #ifClosed: branch--specifically #waitFor{Connection|Accept}For:, analogous to #waitForData/#waitForSendDone families. Leave #waitForDisconnectionFor: alone as returning a boolean, since the socket being destroyed indeed means it is disconnected, so the only failure condition is a timeout. Plus some cleanup of the loops to reduce duplicated code.
Last, cleanly report attempts to retrieve the last socket error code when the socket is already destroyed