Subject: | EINTR on select() can cause invalid read() |
Date: | Wed, 09 Sep 2009 09:46:18 +0100 |
To: | bug-IPC-Run [...] rt.cpan.org |
From: | Tom Molesworth <tmolesworth [...] humyo.com> |
If select() fails due to interrupted system call (EINTR), _select_loop()
can return without clearing the ROUT, WOUT and EOUT fd mask, which can
lead to a read() being attempted on an fd that's not ready - looks like
this was an oversight when adding the check for EINTR?
Have attached a patch against 0.84 to ensure the FD mask is cleared
before returning from _select_loop.
diff --git a/lib/IPC/Run.pm b/lib/IPC/Run.pm
index 1cb12d0..37b9ab4 100644
--- a/lib/IPC/Run.pm
+++ b/lib/IPC/Run.pm
@@ -3048,8 +3048,11 @@ SELECT:
}
}
last if ! $nfound && $self->{non_blocking};
-
- croak "$! in select" if $nfound < 0 and $! != POSIX::EINTR;
+ if($nfound < 0) {
+ # Clear all fd masks since we have select() error and don't want to attempt a read() or write().
+ $_ = "" foreach ($self->{ROUT}, $self->{WOUT}, $self->{EOUT});
+ croak "$! in select" if $! != POSIX::EINTR;
+ }
## TODO: Analyze the EINTR failure mode and see if this patch
## is adequate and optimal.
## TODO: Add an EINTR test to the test suite.