On Nov 30, 2007, at 12:56 AM, Terry Lambert wrote: <http://bugreport.apple.com>, same place Per complained about this same issue last week. Hmm, I wasn't subscribed last week, but just FYI I couldn't find this by paging back in the archives, nor a search...
Anyway, I'll definitely follow up with bugreport.apple.com. The question was more intended to make sure this was the right mailing list to get the right people to see the issues (instead of say, darwin-kernel or something, but there's probably overlap)
On Nov 30, 2007, at 1:22 AM, Eric Gouriou wrote: If you are using sigaction() to establish the signal handler, it's time to double-check that SA_RESTART is _not_ being set.
I'm using signal(), so I'm guessing I would need to switch over to sigaction to unset SA_RESTART. (tested below — yup!)
However the EINTR behavior is specified for read(2) Sweet! As long as this should be a reliable behavior (on my platforms of interest at least), and now that I can get the signal to interrupt, this solves my problem! :)
I don't know if one can get iostream::read() to avoid calling read(2) again upon receiving that errno.
I've been testing with both direct read() and the iostream::read... I looked up some code and verified that fstream::read does indeed boil down to an EINTR loop so that won't do me any good there. However, apparently cin *does not* do an EINTR loop (see attached sample). This probably isn't something I'd want to rely on though. However, streambuf's aren't particularly hard to write, (we're using an iostream because we already have a couple custom streambufs btw...) so if I *really* want to follow this path I could require usage of our non-EINTR looping streambufs to allow cancelability.
Ugly as it is, this actually sounds better than the current hack that essentially kills the thread from within the signal handler — this will allow me to test for the error exit, and then throw an exception within the thread itself, providing controlled and proper cleanup on the way out.
What's particularly sad is that this sounds even better than the currently available pthread_cancel functionality (on OS X), since it will handle more system calls and actually do a proper stack unwind! I realize it's still a rather sketchy hack though -- I don't know if I can trust portable iostream handling of EINTR, so that could be a minor headache to avoid the built-in streambuf types in my particular case. :-/
Thanks very much for the insights!!! -ethan
A working sample solution is attached for future reference:
$ g++ -o test solution.cc -lpthread -Wall && ./test launched interrupting waiting interrupted blocking call: Interrupted system call Foo was cancelled cancel exception handler unlock testing lock still works... working!
|