@@ -74,6 +74,7 @@ def _path_importer_cache(cls, path):
7474import os
7575import pickle as py_pickle
7676import pstats
77+ import pty
7778import signal
7879import socket
7980import struct
@@ -544,8 +545,17 @@ def set_cloexec(fd):
544545 they must be explicitly closed through some other means, such as
545546 :func:`mitogen.fork.on_fork`.
546547 """
548+ stdfds = [
549+ stdfd
550+ for stdio , stdfd in [
551+ (sys .stdin , pty .STDIN_FILENO ),
552+ (sys .stdout , pty .STDOUT_FILENO ),
553+ (sys .stderr , pty .STDERR_FILENO ),
554+ ]
555+ if stdio is not None and not stdio .closed
556+ ]
557+ assert fd not in stdfds , 'fd %r is one of the stdio fds: %r' % (fd , stdfds )
547558 flags = fcntl .fcntl (fd , fcntl .F_GETFD )
548- assert fd > 2 , 'fd %r <= 2' % (fd ,)
549559 fcntl .fcntl (fd , fcntl .F_SETFD , flags | fcntl .FD_CLOEXEC )
550560
551561
@@ -4019,7 +4029,9 @@ def _setup_master(self):
40194029 in_fp = os .fdopen (os .dup (in_fd ), 'rb' , 0 )
40204030 os .close (in_fd )
40214031
4022- out_fp = os .fdopen (os .dup (self .config .get ('out_fd' , 1 )), 'wb' , 0 )
4032+ out_fd = self .config .get ('out_fd' , pty .STDOUT_FILENO )
4033+ out_fd2 = os .dup (out_fd )
4034+ out_fp = os .fdopen (out_fd2 , 'wb' , 0 )
40234035 self .stream = MitogenProtocol .build_stream (
40244036 self .router ,
40254037 parent_id ,
@@ -4103,7 +4115,13 @@ def _nullify_stdio(self):
41034115 Open /dev/null to replace stdio temporarily. In case of odd startup,
41044116 assume we may be allocated a standard handle.
41054117 """
4106- for stdfd , mode in ((0 , os .O_RDONLY ), (1 , os .O_RDWR ), (2 , os .O_RDWR )):
4118+ for stdio , stdfd , mode in [
4119+ (sys .stdin , pty .STDIN_FILENO , os .O_RDONLY ),
4120+ (sys .stdout , pty .STDOUT_FILENO , os .O_RDWR ),
4121+ (sys .stderr , pty .STDERR_FILENO , os .O_RDWR ),
4122+ ]:
4123+ if stdio is None :
4124+ continue
41074125 fd = os .open ('/dev/null' , mode )
41084126 if fd != stdfd :
41094127 os .dup2 (fd , stdfd )
@@ -4119,8 +4137,9 @@ def _preserve_tty_fp(self):
41194137 avoid receiving SIGHUP.
41204138 """
41214139 try :
4122- if os .isatty (2 ):
4123- self .reserve_tty_fp = os .fdopen (os .dup (2 ), 'r+b' , 0 )
4140+ if os .isatty (pty .STDERR_FILENO ):
4141+ reserve_tty_fd = os .dup (pty .STDERR_FILENO )
4142+ self .reserve_tty_fp = os .fdopen (reserve_tty_fd , 'r+b' , 0 )
41244143 set_cloexec (self .reserve_tty_fp .fileno ())
41254144 except OSError :
41264145 pass
@@ -4140,13 +4159,18 @@ def _setup_stdio(self):
41404159 self ._nullify_stdio ()
41414160
41424161 self .loggers = []
4143- for name , fd in (('stdout' , 1 ), ('stderr' , 2 )):
4144- log = IoLoggerProtocol .build_stream (name , fd )
4162+ for stdio , stdfd , name in [
4163+ (sys .stdout , pty .STDOUT_FILENO , 'stdout' ),
4164+ (sys .stderr , pty .STDERR_FILENO , 'stderr' ),
4165+ ]:
4166+ if stdio is None :
4167+ continue
4168+ log = IoLoggerProtocol .build_stream (name , stdfd )
41454169 self .broker .start_receive (log )
41464170 self .loggers .append (log )
41474171
41484172 # Reopen with line buffering.
4149- sys .stdout = os .fdopen (1 , 'w' , 1 )
4173+ sys .stdout = os .fdopen (pty . STDOUT_FILENO , 'w' , 1 )
41504174
41514175 def main (self ):
41524176 self ._setup_master ()
0 commit comments