-
Notifications
You must be signed in to change notification settings - Fork 541
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
use a stack of self._fds_to_close to prevent double closes #481
Changes from all commits
b1f4f3d
757e39c
730dd1a
ddeb5e1
f4f57f6
d5fe279
5926386
aeb5560
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ cdef class UVProcess(UVHandle): | |
object _preexec_fn | ||
bint _restore_signals | ||
|
||
set _fds_to_close | ||
list _fds_to_close | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @fantix I think there's a proper |
||
|
||
# Attributes used to compose uv_process_options_t: | ||
uv.uv_process_options_t options | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -7,7 +7,7 @@ cdef class UVProcess(UVHandle): | |||||||||||
self.uv_opt_args = NULL | ||||||||||||
self._returncode = None | ||||||||||||
self._pid = None | ||||||||||||
self._fds_to_close = set() | ||||||||||||
self._fds_to_close = list() | ||||||||||||
self._preexec_fn = None | ||||||||||||
self._restore_signals = True | ||||||||||||
self.context = Context_CopyCurrent() | ||||||||||||
|
@@ -69,6 +69,11 @@ cdef class UVProcess(UVHandle): | |||||||||||
'Racing with another loop to spawn a process.') | ||||||||||||
|
||||||||||||
self._errpipe_read, self._errpipe_write = os_pipe() | ||||||||||||
fds_to_close = self._fds_to_close | ||||||||||||
self._fds_to_close = None | ||||||||||||
fds_to_close.append(self._errpipe_read) | ||||||||||||
# add the write pipe last so we can close it early | ||||||||||||
fds_to_close.append(self._errpipe_write) | ||||||||||||
graingert marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
try: | ||||||||||||
os_set_inheritable(self._errpipe_write, True) | ||||||||||||
|
||||||||||||
|
@@ -100,8 +105,8 @@ cdef class UVProcess(UVHandle): | |||||||||||
|
||||||||||||
self._finish_init() | ||||||||||||
|
||||||||||||
os_close(self._errpipe_write) | ||||||||||||
self._errpipe_write = -1 | ||||||||||||
# close the write pipe early | ||||||||||||
os_close(fds_to_close.pop()) | ||||||||||||
|
||||||||||||
if preexec_fn is not None: | ||||||||||||
errpipe_data = bytearray() | ||||||||||||
|
@@ -115,17 +120,8 @@ cdef class UVProcess(UVHandle): | |||||||||||
break | ||||||||||||
|
||||||||||||
finally: | ||||||||||||
os_close(self._errpipe_read) | ||||||||||||
try: | ||||||||||||
os_close(self._errpipe_write) | ||||||||||||
except OSError: | ||||||||||||
# Might be already closed | ||||||||||||
pass | ||||||||||||
|
||||||||||||
fds_to_close = self._fds_to_close | ||||||||||||
self._fds_to_close = None | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yep I see it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I moved it up so that _close_after_spawn can't interfere with the errpipe_write fd |
||||||||||||
for fd in fds_to_close: | ||||||||||||
os_close(fd) | ||||||||||||
while fds_to_close: | ||||||||||||
os_close(fds_to_close.pop()) | ||||||||||||
|
||||||||||||
for fd in restore_inheritable: | ||||||||||||
os_set_inheritable(fd, False) | ||||||||||||
|
@@ -202,7 +198,7 @@ cdef class UVProcess(UVHandle): | |||||||||||
if self._fds_to_close is None: | ||||||||||||
raise RuntimeError( | ||||||||||||
'UVProcess._close_after_spawn called after uv_spawn') | ||||||||||||
self._fds_to_close.add(fd) | ||||||||||||
self._fds_to_close.append(fd) | ||||||||||||
|
||||||||||||
def __dealloc__(self): | ||||||||||||
if self.uv_opt_env is not NULL: | ||||||||||||
|
@@ -500,10 +496,7 @@ cdef class UVProcessTransport(UVProcess): | |||||||||||
# shouldn't ever happen | ||||||||||||
raise RuntimeError('cannot apply subprocess.STDOUT') | ||||||||||||
|
||||||||||||
newfd = os_dup(io[1]) | ||||||||||||
os_set_inheritable(newfd, True) | ||||||||||||
self._close_after_spawn(newfd) | ||||||||||||
io[2] = newfd | ||||||||||||
io[2] = self._file_redirect_stdio(io[1]) | ||||||||||||
Comment on lines
-503
to
+499
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when reviewing all the calls to uvloop/uvloop/handles/process.pyx Lines 398 to 402 in 5926386
|
||||||||||||
elif _stderr == subprocess_DEVNULL: | ||||||||||||
io[2] = self._file_devnull() | ||||||||||||
else: | ||||||||||||
|
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.
you don't actually need a preexec_fn to trigger the double close it just made it slow enough that the race was more detectable