Open cagney opened 5 years ago
fd & tty should be non-inheritable already (by default), so there would be no race and the os.set_inheritable and POSIX_SPAWN_CLOSE are both unnecessary.
Documentation states that all FDs are non-inheritable by default in Python 3.4+, and I have confirmed this in Python 3.6.6.
fd & tty should be non-inheritable already (by default), so there would be no race and the os.set_inheritable and POSIX_SPAWN_CLOSE are both unnecessary.
Documentation states that all FDs are non-inheritable by default in Python 3.4+, and I have confirmed this in Python 3.6.6.
The race is in os.openpty(). Since openpty() returns an inheritable master and slave, a parallel for made after openpty() returns but before inheritable is cleared would inherit those FDs.
if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
goto posix_error;
if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
goto error;
if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
goto error;
but yes, the os.set_inheritable and POSIX_SPAWN_CLOSE could be dropped
That region of code is protected by the GIL. No race.
(Copying my comment from #52)
I don't know how to combine the os.spawn*
functions - or anything that doesn't involve a fork - with setting up a new pty as the controlling terminal of the child process. I suspect it's not possible, but it would be very nice if it was. If you figure it out, please let me know!
The attached patch is an experiment in using Python 3.8's os.posix_spawn() in ptyprocess. Since it doesn't use fork() it eliminates all those problems. A simple test using pexpect.interact() seemed to work.
I know it has a race with inheritable when called in parallel; and I'm sure there's more.
ptyprocess-posix-spawn.patch.gz
The change looks bigger than it is because I indented all the old code. Below is what matters, which I've included so it is easier to pick it apart....