[iostreams] interrupted reads / writes
Hello, I have been toying with a framework for process management. I have opted to catch SIGCHLD in my signal handler to handle child processes. However, boost::iostreams does not seem to recognize system calls which are interrupted, and throws exceptions. Witness ./libs/iostreams/src/file_descriptor.cpp: errno = 0; std::streamsize result = BOOST_RTL(read)(pimpl_->fd_, s, n); if (errno != 0) throw detail::bad_read(); return result == 0 ? -1 : result; if ::read fails with errno == EINTR, a bad_read will result. This is unfortunate, as caught SIGCHLD signals will result in spurious errors, as the following strace shows: ... read(9, 0x95d83ac, 4096) = ? ERESTARTSYS (To be restarted) --- SIGCHLD (Child exited) @ 0 (0) --- waitpid(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG) = 2407 sigreturn() = ? (mask now []) write(2, "terminate called after throwing "..., 48) = 48 write(2, "std::ios_base::failure", 22) = 22 write(2, "\'\n", 2) = 2 write(2, " what(): ", 11) = 11 write(2, "bad read", 8) = 8 write(2, "\n", 1) = 1 ... As I understand it, boost was going to use ::read(), but the SIGCHLD got in between, resulting in a an exception being thrown. I realize that boost::process is not up and running yet, so this might be a usage conflict of posix & boost. Can somebody please enlighten me what the usage pattern here should be? Thanks in advance, Marcus
Marcus Alanen wrote:
Hello,
I have been toying with a framework for process management. I have opted to catch SIGCHLD in my signal handler to handle child processes. However, boost::iostreams does not seem to recognize system calls which are interrupted, and throws exceptions.
Witness ./libs/iostreams/src/file_descriptor.cpp:
errno = 0; std::streamsize result = BOOST_RTL(read)(pimpl_->fd_, s, n); if (errno != 0) throw detail::bad_read(); return result == 0 ? -1 : result;
if ::read fails with errno == EINTR, a bad_read will result. This is unfortunate, as caught SIGCHLD signals will result in spurious errors, as the following strace shows:
... read(9, 0x95d83ac, 4096) = ? ERESTARTSYS (To be restarted) --- SIGCHLD (Child exited) @ 0 (0) --- waitpid(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG) = 2407 sigreturn() = ? (mask now []) write(2, "terminate called after throwing "..., 48) = 48 write(2, "std::ios_base::failure", 22) = 22 write(2, "\'\n", 2) = 2 write(2, " what(): ", 11) = 11 write(2, "bad read", 8) = 8 write(2, "\n", 1) = 1 ...
As I understand it, boost was going to use ::read(), but the SIGCHLD got in between, resulting in a an exception being thrown.
I realize that boost::process is not up and running yet, so this might be a usage conflict of posix & boost. Can somebody please enlighten me what the usage pattern here should be?
This is posix. The usage pattern should be to specify the SA_RESTART flag when you install your signal handler. Checking for EINTR and adding retry logic after every system call, is not a realistic alternative. HTH, Ian McCulloch
Sorry I didn't see this message eariler. Marcus Alanen wrote:
Hello,
I have been toying with a framework for process management. I have opted to catch SIGCHLD in my signal handler to handle child processes. However, boost::iostreams does not seem to recognize system calls which are interrupted, and throws exceptions.
Right.
Witness ./libs/iostreams/src/file_descriptor.cpp:
errno = 0; std::streamsize result = BOOST_RTL(read)(pimpl_->fd_, s, n); if (errno != 0) throw detail::bad_read(); return result == 0 ? -1 : result;
if ::read fails with errno == EINTR, a bad_read will result. This is unfortunate, as caught SIGCHLD signals will result in spurious errors, as the following strace shows: ... read(9, 0x95d83ac, 4096) = ? ERESTARTSYS (To be restarted) --- SIGCHLD (Child exited) @ 0 (0) --- waitpid(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG) = 2407 sigreturn() = ? (mask now []) write(2, "terminate called after throwing "..., 48) = 48 write(2, "std::ios_base::failure", 22) = 22 write(2, "\'\n", 2) = 2 write(2, " what(): ", 11) = 11 write(2, "bad read", 8) = 8 write(2, "\n", 1) = 1 ...
As I understand it, boost was going to use ::read(), but the SIGCHLD got in between, resulting in a an exception being thrown.
I don't understand this sentence.
I realize that boost::process is not up and running yet, so this might be a usage conflict of posix & boost. Can somebody please enlighten me what the usage pattern here should be?
I agree with Ian McCulloch's reply. What are you thinking would be a better aproach?
Thanks in advance, Marcus
-- Jonathan Turkanis www.kangaroologic.com
Jonathan Turkanis wrote:
I realize that boost::process is not up and running yet, so this might be a usage conflict of posix & boost. Can somebody please enlighten me what the usage pattern here should be? I agree with Ian McCulloch's reply. What are you thinking would be a better aproach?
Having thought about this further, and actually tried SA_RESTART, it seems to work nicely, and there probably is no other useful alternative. My thanks to Ian and you. Marcus
participants (3)
-
Ian McCulloch
-
Jonathan Turkanis
-
Marcus Alanen