From: Zac Medico Date: Wed, 26 Sep 2007 20:01:23 +0000 (-0000) Subject: Set non-blocking mode on the pty master file descriptor while X-Git-Tag: v2.2_pre1~776 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=31e53c35e81dbc93ac1226f29fb5c5955817b74a;p=portage.git Set non-blocking mode on the pty master file descriptor while the slave file descriptor is still held open since otherwise the fcntl call can fail on FreeBSD (the child process might have already exited and closed the slave file descriptor so we have to keep it open in order to avoid FreeBSD potentially generating an EAGAIN exception). This appoach is cleaner than triggering the exception and being forced to handle it somehow. svn path=/main/trunk/; revision=7835 --- diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 7a2fa0855..24b246be7 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -2442,6 +2442,16 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakero writemsg("openpty failed: '%s'\n" % str(e), noiselevel=1) del e master_fd, slave_fd = os.pipe() + + # We must set non-blocking mode before we close the slave_fd + # since otherwise the fcntl call can fail on FreeBSD (the child + # process might have already exited and closed slave_fd so we + # have to keep it open in order to avoid FreeBSD potentially + # generating an EAGAIN exception). + import fcntl + fcntl.fcntl(master_fd, fcntl.F_SETFL, + fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK) + fd_pipes.setdefault(0, sys.stdin.fileno()) fd_pipes_orig = fd_pipes.copy() if got_pty and os.isatty(fd_pipes_orig[1]): @@ -2488,7 +2498,7 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakero try: mypids.extend(spawn_func(mystring, env=env, **keywords)) finally: - if slave_fd: + if logfile: os.close(slave_fd) if sesandbox: selinux.setexec(None) @@ -2503,26 +2513,14 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakero iwtd = [master_file] owtd = [] ewtd = [] - import array, fcntl, select - fd_flags = {} - for f in iwtd: - fd_flags[f] = fcntl.fcntl(f.fileno(), fcntl.F_GETFL) + import array, select buffsize = 65536 eof = False - # Use non-blocking mode to prevent read - # calls from blocking indefinitely. - try: - fcntl.fcntl(master_file.fileno(), fcntl.F_SETFL, - fd_flags[master_file] | os.O_NONBLOCK) - except EnvironmentError, e: - if e.errno != errno.EAGAIN: - raise - del e - # The EAGAIN error signals eof on FreeBSD. - eof = True while not eof: events = select.select(iwtd, owtd, ewtd) for f in events[0]: + # Use non-blocking mode to prevent read + # calls from blocking indefinitely. buf = array.array('B') try: buf.fromfile(f, buffsize)