-
Notifications
You must be signed in to change notification settings - Fork 71
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 and prefer os.posix_spawn() when available #54
base: master
Are you sure you want to change the base?
Conversation
Python 3.8 has added os.posix_spawn(), this changes ptyprocess to use it when available. Since os.posix_spawn() completey bypasses os.fork(), pty.fork(), it avoids problems with logging locks and code needing to be thread-safe.
Thanks, this is interesting. I have a couple of concerns, though. Most significantly, the functions to fork a process into a pty all have some extra code to make the new tty the controlling tty of the new process. Here's ptyprocess' fallback: ptyprocess/ptyprocess/_fork_pty.py Line 31 in 3931cd4
Here it is in Python's stdlib: And here it is in glibc's forkpty function: https://github.com/lattera/glibc/blob/895ef79e04a953cac1493863bcae29ad85657ee1/login/login_tty.c I don't think the Secondly, the Presumably the glibc implementation is pretty good, but I'd still have some concern that we're trading one set of problems for another. The possibility that the whole block needs wrapping in a Python-level threading lock doesn't inspire confidence - even if it ultimately turns out not to need that, the fact that it looks like it might isn't great. |
(non-inheritable is code for O_CLOEXEC)
Yea. Below are extracts from a BSD implementation of login_tty() (its the same as glibc, but simpler):
For screwing around with the process group, posix_spawn() seems to have two mechanisms:
It seems to be missing. I'm not seeing problems, but then I'm not trying to run something like an interactive bash in the sub-process. I'll look into it.
this is handled by the file_actions=... argument.
BTW, on Solaris and NetBSD, at least, it's implemented as a system call.
The problem's with os.openpty() / openpty(3) which returns the PTY/TTY without O_CLOEXEC set. This means that fork()/exec() in a separate thread would have the FD left open :-( However, this also means I can simplify things and just wrap the os.openpty() and setting non-inheritable. |
Drop setsid=True which is less portable but more useful.
Having done some more reading, I still think the missing 'controlling tty' part is important. It looks like this may be used for:
I also looked into the source code of libvte, the terminal emulator library used by Gnome terminal (among other applications). As best I can tell, it also uses As attractive as it is, I think |
Python 3.8 has added os.posix_spawn(), this changes ptyprocess
to use it when available.
Since os.posix_spawn() completey bypasses os.fork(), pty.fork(),
it avoids problems with logging locks and code needing to be thread-safe.