2 # Copyright (c) 2002-2003 ActiveState 
   3 # See LICENSE.txt for license details. 
   4 """ Contents of LICENSE.txt: 
   5 Permission is hereby granted, free of charge, to any person obtaining a 
   6 copy of this software and associated documentation files (the 
   7 "Software"), to deal in the Software without restriction, including 
   8 without limitation the rights to use, copy, modify, merge, publish, 
   9 distribute, sublicense, and/or sell copies of the Software, and to 
  10 permit persons to whom the Software is furnished to do so, subject to 
  11 the following conditions: 
  13 The above copyright notice and this permission notice shall be included 
  14 in all copies or substantial portions of the Software. 
  16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
  17 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
  18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
  19 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
  20 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
  21 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
  22 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
  26     Python interface for process control. 
  28     This module defines three Process classes for spawning, 
  29     communicating and control processes. They are: Process, ProcessOpen, 
  30     ProcessProxy. All of the classes allow one to specify the command (cmd), 
  31     starting working directory (cwd), and environment to create for the 
  32     new process (env) and to "wait" for termination of the child and 
  36         Use this class to simply launch a process (either a GUI app or a 
  37         console app in a new console) with which you do not intend to 
  38         communicate via it std handles. 
  41         Think of this as a super version of Python's os.popen3() method. 
  42         This spawns the given command and sets up pipes for 
  43         stdin/stdout/stderr which can then be used to communicate with 
  47         This is a heavy-weight class that, similar to ProcessOpen, 
  48         spawns the given commands and sets up pipes to the child's 
  49         stdin/stdout/stderr. However, it also starts three threads to 
  50         proxy communication between each of the child's and parent's std 
  51         handles. At the parent end of this communication are, by 
  52         default, IOBuffer objects. You may specify your own objects here 
  53         (usually sub-classing from IOBuffer, which handles some 
  54         synchronization issues for you). The result is that it is 
  55         possible to have your own IOBuffer instance that gets, say, a 
  56         .write() "event" for every write that the child does on its 
  59         Understanding ProcessProxy is pretty complex. Some examples 
  60         below attempt to help show some uses. Here is a diagram of the 
  64                ,---->->->------'   ^   `------>->->----, 
  66            IOBuffer             IOBuffer            IOBuffer         
  67            (p.stdout)           (p.stderr)          (p.stdin) 
  69            _OutFileProxy        _OutFileProxy       _InFileProxy 
  72                `----<-<-<------,   |   ,------<-<-<----' 
  77         p = process.<Process class>(cmd='echo hi', ...) 
  78         #... use the various methods and attributes 
  81       A simple 'hello world': 
  83         >>> p = process.ProcessOpen(['echo', 'hello']) 
  86         >>> p.wait()   # .wait() returns the child's exit status 
  89       Redirecting the stdout handler: 
  91         >>> p = process.ProcessProxy(['echo', 'hello'], stdout=sys.stdout) 
  94       Using stdin (need to use ProcessProxy here because it defaults to 
  95       text-mode translation on Windows, ProcessOpen does not support 
  97         >>> p = process.ProcessProxy(['sort']) 
  98         >>> p.stdin.write('5\n') 
  99         >>> p.stdin.write('2\n') 
 100         >>> p.stdin.write('7\n') 
 105       Specifying environment variables: 
 106         >>> p = process.ProcessOpen(['perl', '-e', 'print $ENV{FOO}']) 
 109         >>> p = process.ProcessOpen(['perl', '-e', 'print $ENV{FOO}'], 
 110         ...                         env={'FOO':'bar'}) 
 114       Killing a long running process (On Linux, to poll you must use 
 116         >>> p = ProcessOpen(['perl', '-e', 'while (1) {}']) 
 118         ...     p.wait(os.WNOHANG)  # poll to see if is process still running 
 119         ... except ProcessError, ex: 
 120         ...     if ex.errno == ProcessProxy.WAIT_TIMEOUT: 
 121         ...             print "process is still running" 
 123         process is still running 
 128       Providing objects for stdin/stdout/stderr: 
 129         XXX write this, mention IOBuffer subclassing. 
 132 #   - Discuss the decision to NOT have the stdout/stderr _OutFileProxy's 
 133 #     wait for process termination before closing stdin. It will just 
 134 #     close stdin when stdout is seen to have been closed. That is 
 135 #     considered Good Enough (tm). Theoretically it would be nice to 
 136 #     only abort the stdin proxying when the process terminates, but 
 137 #     watching for process termination in any of the parent's thread 
 138 #     adds the undesired condition that the parent cannot exit with the 
 139 #     child still running. That sucks. 
 140 #     XXX Note that I don't even know if the current stdout proxy even 
 141 #         closes the stdin proxy at all. 
 142 #   - DavidA: if I specify "unbuffered" for my stdin handler (in the 
 143 #     ProcessProxy constructor) then the stdin IOBuffer should do a 
 144 #     fparent.read() rather than a fparent.readline(). TrentM: can I do 
 145 #     that? What happens? 
 153 if sys
.platform
.startswith("win"): 
 161     # constants pulled from win32con to save memory 
 162     VER_PLATFORM_WIN32_WINDOWS 
= 1 
 166     DUPLICATE_SAME_ACCESS 
= 2 
 174 class ProcessError(Exception): 
 175     def __init__(self
, msg
, errno
=-1): 
 176         Exception.__init
__(self
, msg
) 
 180 #---- internal logging facility 
 183     DEBUG
, INFO
, WARN
, ERROR
, FATAL 
= range(5) 
 184     def __init__(self
, name
, level
=None, streamOrFileName
=sys
.stderr
): 
 187             self
.level 
= self
.WARN
 
 190         if type(streamOrFileName
) == types
.StringType
: 
 191             self
.stream 
= open(streamOrFileName
, 'w') 
 192             self
._opennedStream 
= 1 
 194             self
.stream 
= streamOrFileName
 
 195             self
._opennedStream 
= 0 
 197         if self
._opennedStream
: 
 199     def _getLevelName(self
, level
): 
 207         return levelNameMap
[level
] 
 208     def log(self
, level
, msg
, *args
): 
 209         if level 
< self
.level
: 
 211         message 
= "%s: %s:" % (self
.name
, self
._getLevelName
(level
).lower()) 
 212         message 
= message 
+ (msg 
% args
) + "\n" 
 213         self
.stream
.write(message
) 
 215     def debug(self
, msg
, *args
): 
 216         self
.log(self
.DEBUG
, msg
, *args
) 
 217     def info(self
, msg
, *args
): 
 218         self
.log(self
.INFO
, msg
, *args
) 
 219     def warn(self
, msg
, *args
): 
 220         self
.log(self
.WARN
, msg
, *args
) 
 221     def error(self
, msg
, *args
): 
 222         self
.log(self
.ERROR
, msg
, *args
) 
 223     def fatal(self
, msg
, *args
): 
 224         self
.log(self
.FATAL
, msg
, *args
) 
 227 #   - 'log' to log normal process handling 
 228 #   - 'logres' to track system resource life 
 229 #   - 'logfix' to track wait/kill proxying in _ThreadFixer 
 230 if 1:   # normal/production usage 
 231     log 
= Logger("process", Logger
.WARN
) 
 232 else:   # development/debugging usage 
 233     log 
= Logger("process", Logger
.DEBUG
, sys
.stdout
) 
 234 if 1:   # normal/production usage 
 235     logres 
= Logger("process.res", Logger
.WARN
) 
 236 else:   # development/debugging usage 
 237     logres 
= Logger("process.res", Logger
.DEBUG
, sys
.stdout
) 
 238 if 1:   # normal/production usage 
 239     logfix 
= Logger("process.waitfix", Logger
.WARN
) 
 240 else:   # development/debugging usage 
 241     logfix 
= Logger("process.waitfix", Logger
.DEBUG
, sys
.stdout
) 
 247 _version_ 
= (0, 5, 0) 
 249 # List of registered processes (see _(un)registerProcess). 
 254 #---- internal support routines 
 257     """Escape the given command line argument for the shell.""" 
 258     #XXX There is a probably more that we should escape here. 
 259     return arg
.replace('"', r
'\"') 
 263     r
"""Join an arglist to a string appropriate for running. 
 266         >>> _joinArgv(['foo', 'bar "baz']) 
 271         if ' ' in arg 
or ';' in arg
: 
 272             cmdstr 
+= '"%s"' % _escapeArg(arg
) 
 274             cmdstr 
+= _escapeArg(arg
) 
 276     if cmdstr
.endswith(' '): cmdstr 
= cmdstr
[:-1]  # strip trailing space 
 280 def _getPathFromEnv(env
): 
 281     """Return the PATH environment variable or None. 
 283     Do the right thing for case sensitivity per platform. 
 284     XXX Icky. This guarantee of proper case sensitivity of environment 
 285         variables should be done more fundamentally in this module. 
 287     if sys
.platform
.startswith("win"): 
 288         for key 
in env
.keys(): 
 289             if key
.upper() == "PATH": 
 294         if env
.has_key("PATH"): 
 300 def _whichFirstArg(cmd
, env
=None): 
 301     """Return the given command ensuring that the first arg (the command to 
 302     launch) is a full path to an existing file. 
 304     Raise a ProcessError if no such executable could be found. 
 306     # Parse out the first arg. 
 307     if cmd
.startswith('"'): 
 308         # The .replace() is to ensure it does not mistakenly find the 
 309         # second '"' in, say (escaped quote): 
 310         #           "C:\foo\"bar" arg1 arg2 
 311         idx 
= cmd
.replace('\\"', 'XX').find('"', 1) 
 313             raise ProcessError("Malformed command: %r" % cmd
) 
 314         first
, rest 
= cmd
[1:idx
], cmd
[idx
+1:] 
 318             first
, rest 
= cmd
.split(' ', 1) 
 320             first
, rest 
= cmd
, "" 
 322     # Ensure the first arg is a valid path to the appropriate file. 
 325         altpath 
= [os
.path
.dirname(first
)] 
 326         firstbase 
= os
.path
.basename(first
) 
 327         candidates 
= list(which
.which(firstbase
, path
=altpath
)) 
 329         altpath 
= _getPathFromEnv(env
) 
 331             candidates 
= list(which
.which(first
, altpath
.split(os
.pathsep
))) 
 333             candidates 
= list(which
.which(first
)) 
 335         candidates 
= list(which
.which(first
)) 
 337         return _joinArgv( [candidates
[0]] ) + ' ' + rest
 
 339         raise ProcessError("Could not find an appropriate leading command "\
 
 343 if sys
.platform
.startswith("win"): 
 344     def _SaferCreateProcess(appName
,        # app name 
 346                             processSA
,      # process security attributes  
 347                             threadSA
,       # thread security attributes  
 348                             inheritHandles
, # are handles are inherited 
 349                             creationFlags
,  # creation flags  
 351                             cwd
,            # current working directory 
 352                             si
):            # STARTUPINFO pointer 
 353         """If CreateProcess fails from environment type inconsistency then 
 354         fix that and try again. 
 356         win32process.CreateProcess requires that all environment keys and 
 357         values either be all ASCII or all unicode. Try to remove this burden 
 358         from the user of process.py. 
 360         isWin9x 
= win32api
.GetVersionEx()[3] == VER_PLATFORM_WIN32_WINDOWS
 
 361         # On Win9x all keys and values of 'env' must be ASCII (XXX 
 362         # Actually this is probably only true if the Unicode support 
 363         # libraries, which are not installed by default, are not 
 364         # installed). On other Windows flavours all keys and values of 
 365         # 'env' must all be ASCII *or* all Unicode. We will try to 
 366         # automatically convert to the appropriate type, issuing a 
 367         # warning if such an automatic conversion is necessary. 
 369         #XXX Komodo 2.0 Beta 1 hack. This requirement should be 
 370         #    pushed out to Komodo code using process.py. Or should it? 
 373             for key
, value 
in env
.items(): 
 374                 aenv
[str(key
)] = str(value
) 
 378 _SaferCreateProcess(appName=%r, 
 383 """, appName
, cmd
, env
, cwd
, os
.getcwd()) 
 385             hProcess
, hThread
, processId
, threadId\
 
 386                 = win32process
.CreateProcess(appName
, cmd
, processSA
, 
 387                                              threadSA
, inheritHandles
, 
 388                                              creationFlags
, env
, cwd
, si
) 
 389         except TypeError, ex
: 
 390             if ex
.args 
== ('All dictionary items must be strings, or all must be unicode',): 
 391                 # Try again with an all unicode environment. 
 392                 #XXX Would be nice if didn't have to depend on the error 
 393                 #    string to catch this. 
 394                 #XXX Removing this warning for 2.3 release. See bug 
 395                 #    23215. The right fix is to correct the PHPAppInfo 
 396                 #    stuff to heed the warning. 
 398                 #warnings.warn('env: ' + str(ex), stacklevel=4) 
 402                         for key
, value 
in env
.items(): 
 403                             aenv
[str(key
)] = str(value
) 
 404                     except UnicodeError, ex
: 
 405                         raise ProcessError(str(ex
)) 
 409                     for key
, val 
in env
.items(): 
 410                         uenv
[unicode(key
)] = unicode(val
) 
 412                 hProcess
, hThread
, processId
, threadId\
 
 413                     = win32process
.CreateProcess(appName
, cmd
, processSA
, 
 414                                                  threadSA
, inheritHandles
, 
 415                                                  creationFlags
, env
, cwd
, 
 419         return hProcess
, hThread
, processId
, threadId
 
 422 # Maintain references to all spawned ProcessProxy objects to avoid hangs. 
 423 #   Otherwise, if the user lets the a ProcessProxy object go out of 
 424 #   scope before the process has terminated, it is possible to get a 
 425 #   hang (at least it *used* to be so when we had the 
 426 #   win32api.CloseHandle(<stdin handle>) call in the __del__() method). 
 427 #   XXX Is this hang possible on Linux as well? 
 428 # A reference is removed from this list when the process's .wait or 
 429 # .kill method is called. 
 430 # XXX Should an atexit() handler be registered to kill all curently 
 431 #     running processes? Else *could* get hangs, n'est ce pas? 
 432 def _registerProcess(process
): 
 434     log
.info("_registerprocess(process=%r)", process
) 
 436     # Clean up zombie processes. 
 437     #   If the user does not call .wait() or .kill() on processes then 
 438     #   the ProcessProxy object will not get cleaned up until Python 
 439     #   exits and _processes goes out of scope. Under heavy usage that 
 440     #   is a big memory waste. Cleaning up here alleviates that. 
 441     for p 
in _processes
[:]: # use copy of _process, because we may modifiy it 
 443             # poll to see if is process still running 
 444             if sys
.platform
.startswith("win"): 
 449             _unregisterProcess(p
) 
 450         except ProcessError
, ex
: 
 451             if ex
.errno 
== ProcessProxy
.WAIT_TIMEOUT
: 
 456     _processes
.append(process
) 
 458 def _unregisterProcess(process
): 
 460     log
.info("_unregisterProcess(process=%r)", process
) 
 462         _processes
.remove(process
) 
 468 def _fixupCommand(cmd
, env
=None): 
 469     """Fixup the command string so it is launchable via CreateProcess. 
 471     One cannot just launch, say "python", via CreateProcess. A full path 
 472     to an executable is required. In general there are two choices: 
 473         1. Launch the command string via the shell. The shell will find 
 474            the fullpath to the appropriate executable. This shell will 
 475            also be able to execute special shell commands, like "dir", 
 476            which don't map to an actual executable. 
 477         2. Find the fullpath to the appropriate executable manually and 
 480     Option (1) is preferred because you don't have to worry about not 
 481     exactly duplicating shell behaviour and you get the added bonus of 
 482     being able to launch "dir" and friends. 
 484     However, (1) is not always an option. Doing so when the shell is 
 485     command.com (as on all Win9x boxes) or when using WinNT's cmd.exe, 
 486     problems are created with .kill() because these shells seem to eat 
 487     up Ctrl-C's and Ctrl-Break's sent via 
 488     win32api.GenerateConsoleCtrlEvent().  Strangely this only happens 
 489     when spawn via this Python interface. For example, Ctrl-C get 
 490     through to hang.exe here: 
 491       C:\> ...\w9xpopen.exe "C:\WINDOWS\COMMAND.COM /c hang.exe" 
 494       >>> p = ProcessOpen('hang.exe') 
 495       # This results in the same command to CreateProcess as 
 499     Hence, for these platforms we fallback to option (2).  Cons: 
 500       - cannot spawn shell commands like 'dir' directly 
 501       - cannot spawn batch files 
 503     if sys
.platform
.startswith("win"): 
 504         # Fixup the command string to spawn.  (Lifted from 
 505         # posixmodule.c::_PyPopenCreateProcess() with some modifications) 
 506         comspec 
= os
.environ
.get("COMSPEC", None) 
 507         win32Version 
= win32api
.GetVersion() 
 509             raise ProcessError("Cannot locate a COMSPEC environment "\
 
 510                                "variable to use as the shell") 
 511         # Explicitly check if we are using COMMAND.COM.  If we 
 512         # are then use the w9xpopen hack. 
 513         elif (win32Version 
& 0x80000000L 
== 0) and\
 
 514              (win32Version 
&        0x5L 
>= 5) and\
 
 515              os
.path
.basename(comspec
).lower() != "command.com": 
 516             # 2000/XP and not using command.com. 
 517             if '"' in cmd 
or "'" in cmd
: 
 518                 cmd 
= comspec 
+ ' /c "%s"' % cmd
 
 520                 cmd 
= comspec 
+ ' /c ' + cmd
 
 521         elif (win32Version 
& 0x80000000L 
== 0) and\
 
 522              (win32Version 
&        0x5L  
< 5) and\
 
 523              os
.path
.basename(comspec
).lower() != "command.com": 
 524             # NT and not using command.com. 
 526                 cmd 
= _whichFirstArg(cmd
, env
) 
 528                 raise ProcessError("Could not find a suitable executable "\
 
 529                     "to launch for '%s'. On WinNT you must manually prefix "\
 
 530                     "shell commands and batch files with 'cmd.exe /c' to "\
 
 531                     "have the shell run them." % cmd
) 
 533             # Oh gag, we're on Win9x and/or using COMMAND.COM. Use the 
 534             # workaround listed in KB: Q150956 
 535             w9xpopen 
= os
.path
.join( 
 536                 os
.path
.dirname(win32api
.GetModuleFileName(0)), 
 538             if not os
.path
.exists(w9xpopen
): 
 539                 # Eeek - file-not-found - possibly an embedding 
 540                 # situation - see if we can locate it in sys.exec_prefix 
 541                 w9xpopen 
= os
.path
.join(os
.path
.dirname(sys
.exec_prefix
), 
 543                 if not os
.path
.exists(w9xpopen
): 
 545                         "Can not locate 'w9xpopen.exe' which is needed "\
 
 546                         "for ProcessOpen to work with your shell or "\
 
 548             ## This would be option (1): 
 549             #cmd = '%s "%s /c %s"'\ 
 550             #      % (w9xpopen, comspec, cmd.replace('"', '\\"')) 
 552                 cmd 
= _whichFirstArg(cmd
, env
) 
 554                 raise ProcessError("Could not find a suitable executable "\
 
 555                     "to launch for '%s'. On Win9x you must manually prefix "\
 
 556                     "shell commands and batch files with 'command.com /c' "\
 
 557                     "to have the shell run them." % cmd
) 
 558             cmd 
= '%s "%s"' % (w9xpopen
, cmd
.replace('"', '\\"')) 
 562     """Wrap a system file object, hiding some nitpicky details. 
 564     This class provides a Python file-like interface to either a Python 
 565     file object (pretty easy job), a file descriptor, or an OS-specific 
 566     file handle (e.g.  Win32 handles to file objects on Windows). Any or 
 567     all of these object types may be passed to this wrapper. If more 
 568     than one is specified this wrapper prefers to work with certain one 
 570         - file descriptor (because usually this allows for 
 571           return-immediately-on-read-if-anything-available semantics and 
 572           also provides text mode translation on Windows) 
 573         - OS-specific handle (allows for the above read semantics) 
 574         - file object (buffering can cause difficulty for interacting 
 575           with spawned programs) 
 577     It also provides a place where related such objects can be kept 
 578     alive together to prevent premature ref-counted collection. (E.g. on 
 579     Windows a Python file object may be associated with a Win32 file 
 580     handle. If the file handle is not kept alive the Python file object 
 581     will cease to function.) 
 583     def __init__(self
, file=None, descriptor
=None, handle
=None): 
 585         self
._descriptor 
= descriptor
 
 586         self
._handle 
= handle
 
 588         if self
._descriptor 
is not None or self
._handle 
is not None: 
 589             self
._lineBuf 
= "" # to support .readline() 
 594     def __getattr__(self
, name
): 
 595         """Forward to the underlying file object.""" 
 596         if self
._file 
is not None: 
 597             return getattr(self
._file
, name
) 
 599             raise ProcessError("no file object to pass '%s' attribute to" 
 602     def _win32Read(self
, nBytes
): 
 604             log
.info("[%s] _FileWrapper.read: waiting for read on pipe", 
 606             errCode
, text 
= win32file
.ReadFile(self
._handle
, nBytes
) 
 607         except pywintypes
.error
, ex
: 
 608             # Ignore errors for now, like "The pipe is being closed.", 
 609             # etc. XXX There *may* be errors we don't want to avoid. 
 610             log
.info("[%s] _FileWrapper.read: error reading from pipe: %s", 
 613         assert errCode 
== 0,\
 
 614                "Why is 'errCode' from ReadFile non-zero? %r" % errCode
 
 616             # Empty text signifies that the pipe has been closed on 
 618             log
.info("[%s] _FileWrapper.read: observed close of parent", 
 620             # Signal the child so it knows to stop listening. 
 624             log
.info("[%s] _FileWrapper.read: read %d bytes from pipe: %r", 
 625                      id(self
), len(text
), text
) 
 628     def read(self
, nBytes
=-1): 
 629         # nBytes <= 0 means "read everything" 
 630         #   Note that we are changing the "read everything" cue to 
 631         #   include 0, because actually doing 
 632         #   win32file.ReadFile(<handle>, 0) results in every subsequent 
 633         #   read returning 0, i.e. it shuts down the pipe. 
 634         if self
._descriptor 
is not None: 
 636                 text
, self
._lineBuf 
= self
._lineBuf
, "" 
 638                     t 
= os
.read(self
._descriptor
, 4092) 
 644                 if len(self
._lineBuf
) >= nBytes
: 
 645                     text
, self
._lineBuf 
=\
 
 646                         self
._lineBuf
[:nBytes
], self
._lineBuf
[nBytes
:] 
 648                     nBytesToGo 
= nBytes 
- len(self
._lineBuf
) 
 649                     text 
= self
._lineBuf 
+ os
.read(self
._descriptor
, 
 653         elif self
._handle 
is not None: 
 655                 text
, self
._lineBuf 
= self
._lineBuf
, "" 
 657                     t 
= self
._win
32Read
(4092) 
 663                 if len(self
._lineBuf
) >= nBytes
: 
 664                     text
, self
._lineBuf 
=\
 
 665                         self
._lineBuf
[:nBytes
], self
._lineBuf
[nBytes
:] 
 667                     nBytesToGo 
= nBytes 
- len(self
._lineBuf
) 
 668                     text
, self
._lineBuf 
=\
 
 669                         self
._lineBuf 
+ self
._win
32Read
(nBytesToGo
), "" 
 671         elif self
._file 
is not None: 
 672             return self
._file
.read(nBytes
) 
 674             raise "FileHandle.read: no handle to read with" 
 677         if self
._descriptor 
is not None or self
._handle 
is not None: 
 679                 #XXX This is not portable to the Mac. 
 680                 idx 
= self
._lineBuf
.find('\n') 
 682                     line
, self
._lineBuf 
=\
 
 683                         self
._lineBuf
[:idx
+1], self
._lineBuf
[idx
+1:] 
 686                     lengthBefore 
= len(self
._lineBuf
) 
 688                     if len(t
) <= lengthBefore
: # no new data was read 
 689                         line
, self
._lineBuf 
= self
._lineBuf
, "" 
 694         elif self
._file 
is not None: 
 695             return self
._file
.readline() 
 697             raise "FileHandle.readline: no handle to read with" 
 700         if self
._descriptor 
is not None or self
._handle 
is not None: 
 703                 line 
= self
.readline() 
 709         elif self
._file 
is not None: 
 710             return self
._file
.readlines() 
 712             raise "FileHandle.readline: no handle to read with" 
 714     def write(self
, text
): 
 715         if self
._descriptor 
is not None: 
 716             os
.write(self
._descriptor
, text
) 
 717         elif self
._handle 
is not None: 
 719                 errCode
, nBytesWritten 
= win32file
.WriteFile(self
._handle
, text
) 
 720             except pywintypes
.error
, ex
: 
 721                 # Ingore errors like "The pipe is being closed.", for 
 723                 log
.info("[%s] _FileWrapper.write: error writing to pipe, "\
 
 726             assert errCode 
== 0,\
 
 727                    "Why is 'errCode' from WriteFile non-zero? %r" % errCode
 
 728             if not nBytesWritten
: 
 729                 # No bytes written signifies that the pipe has been 
 730                 # closed on the child's end. 
 731                 log
.info("[%s] _FileWrapper.write: observed close of pipe", 
 735                 log
.info("[%s] _FileWrapper.write: wrote %d bytes to pipe: %r", 
 736                          id(self
), len(text
), text
) 
 737         elif self
._file 
is not None: 
 738             self
._file
.write(text
) 
 740             raise "FileHandle.write: nothing to write with" 
 743         """Close all associated file objects and handles.""" 
 744         log
.debug("[%s] _FileWrapper.close()", id(self
)) 
 747             if self
._file 
is not None: 
 748                 log
.debug("[%s] _FileWrapper.close: close file", id(self
)) 
 750                 log
.debug("[%s] _FileWrapper.close: done file close", id(self
)) 
 751             if self
._descriptor 
is not None: 
 753                     os
.close(self
._descriptor
) 
 756                         # Ignore: OSError: [Errno 9] Bad file descriptor 
 757                         # XXX *Should* we be ignoring this? It appears very 
 758                         #     *in*frequently in test_wait.py. 
 759                         log
.debug("[%s] _FileWrapper.close: closing "\
 
 760                                   "descriptor raised OSError", id(self
)) 
 763             if self
._handle 
is not None: 
 764                 log
.debug("[%s] _FileWrapper.close: close handle", id(self
)) 
 766                     win32api
.CloseHandle(self
._handle
) 
 767                 except win32api
.error
: 
 768                     log
.debug("[%s] _FileWrapper.close: closing handle raised", 
 771                 log
.debug("[%s] _FileWrapper.close: done closing handle", 
 775         return "<_FileWrapper: file:%r fd:%r os_handle:%r>"\
 
 776                % (self
._file
, self
._descriptor
, self
._handle
) 
 779 class _CountingCloser
: 
 780     """Call .close() on the given object after own .close() is called 
 781     the precribed number of times. 
 783     def __init__(self
, objectsToClose
, count
): 
 785         "objectsToClose" is a list of object on which to call .close(). 
 786         "count" is the number of times this object's .close() method 
 787             must be called before .close() is called on the given objects. 
 789         self
.objectsToClose 
= objectsToClose
 
 792             raise ProcessError("illegal 'count' value: %s" % self
.count
) 
 796         log
.debug("[%d] _CountingCloser.close(): count=%d", id(self
), 
 799             for objectToClose 
in self
.objectsToClose
: 
 800                 objectToClose
.close() 
 804 #---- public interface 
 809     One can optionally specify the starting working directory, the 
 810     process environment, and std handles to have the child process 
 811     inherit (all defaults are the parent's current settings). 'wait' and 
 812     'kill' method allow for control of the child's termination. 
 815     #   - Rename this or merge it with ProcessOpen somehow. 
 817     if sys
.platform
.startswith("win"): 
 818         # .wait() argument constants 
 819         INFINITE 
= win32event
.INFINITE
 
 820         # .wait() return error codes 
 821         WAIT_FAILED 
= win32event
.WAIT_FAILED
 
 822         WAIT_TIMEOUT 
= win32event
.WAIT_TIMEOUT
 
 823         # creation "flags" constants 
 824         # XXX Should drop these and just document usage of 
 825         #     win32process.CREATE_* constants on windows. 
 826         CREATE_NEW_CONSOLE 
= win32process
.CREATE_NEW_CONSOLE
 
 828         # .wait() argument constants 
 830         # .wait() return error codes 
 833         # creation "flags" constants 
 834         CREATE_NEW_CONSOLE 
= 0x10 # same as win32process.CREATE_NEW_CONSOLE 
 836     def __init__(self
, cmd
, cwd
=None, env
=None, flags
=0): 
 837         """Create a child process. 
 839         "cmd" is a command string or argument vector to spawn. 
 840         "cwd" is a working directory in which to start the child process. 
 841         "env" is an environment dictionary for the child. 
 842         "flags" are system-specific process creation flags. On Windows 
 843             this can be a bitwise-OR of any of the win32process.CREATE_* 
 844             constants (Note: win32process.CREATE_NEW_PROCESS_GROUP is always 
 845             OR'd in). On Unix, this is currently ignored. 
 847         log
.info("Process.__init__(cmd=%r, cwd=%r, env=%r, flags=%r)", 
 848                  cmd
, cwd
, env
, flags
) 
 851             raise ProcessError("You must specify a command.") 
 855         if sys
.platform
.startswith("win"): 
 856             self
._flags |
= win32process
.CREATE_NEW_PROCESS_GROUP
 
 858         if sys
.platform
.startswith("win"): 
 859             self
._startOnWindows
() 
 861             self
.__retvalCache 
= None 
 864     def _runChildOnUnix(self
): 
 865         #XXX Errors running the child do *not* get communicated back. 
 867         #XXX Perhaps we should *always* prefix with '/bin/sh -c'? There is a 
 868         #    disparity btwn how this works on Linux and Windows. 
 869         if isinstance(self
._cmd
, types
.StringTypes
): 
 870             # This is easier than trying to reproduce shell interpretation to 
 871             # separate the arguments. 
 872             cmd 
= ['/bin/sh', '-c', self
._cmd
] 
 876         # Close all file descriptors (except std*) inherited from the parent. 
 877         MAXFD 
= 256 # Max number of file descriptors (os.getdtablesize()???) 
 878         for i 
in range(3, MAXFD
): 
 886                 os
.execvpe(cmd
[0], cmd
, self
._env
) 
 888                 os
.execvp(cmd
[0], cmd
) 
 890             os
._exit
(1)  # Should never get here. 
 892     def _forkAndExecChildOnUnix(self
): 
 893         """Fork and start the child process. 
 895         Sets self._pid as a side effect. 
 899             self
._runChildOnUnix
() 
 903     def _startOnUnix(self
): 
 909                 raise ProcessError(msg
=str(ex
), errno
=ex
.errno
) 
 910         self
._forkAndExecChildOnUnix
() 
 916     def _startOnWindows(self
): 
 917         if type(self
._cmd
) in (types
.ListType
, types
.TupleType
): 
 918             # And arg vector was passed in. 
 919             cmd 
= _joinArgv(self
._cmd
) 
 923         si 
= win32process
.STARTUPINFO()  
 924         si
.dwFlags 
= win32process
.STARTF_USESHOWWINDOW
 
 925         si
.wShowWindow 
= SW_SHOWDEFAULT
 
 927         if not (self
._flags 
& self
.CREATE_NEW_CONSOLE
): 
 929             # We cannot then use _fixupCommand because this will cause a 
 930             # shell to be openned as the command is launched. Therefore need 
 931             # to ensure be have the full path to the executable to launch. 
 933                 cmd 
= _whichFirstArg(cmd
, self
._env
) 
 935                 # Could not find the command, perhaps it is an internal 
 936                 # shell command -- fallback to _fixupCommand 
 937                 cmd 
= _fixupCommand(cmd
, self
._env
) 
 939             cmd 
= _fixupCommand(cmd
, self
._env
) 
 940         log
.debug("cmd = %r", cmd
) 
 942         # Start the child process. 
 944             self
._hProcess
, self
._hThread
, self
._processId
, self
._threadId\
 
 945                 = _SaferCreateProcess( 
 948                     None,           # process security attributes  
 949                     None,           # primary thread security attributes  
 950                     0,              # handles are inherited  
 951                     self
._flags
,    # creation flags  
 952                     self
._env
,      # environment 
 953                     self
._cwd
,      # current working directory 
 954                     si
)             # STARTUPINFO pointer  
 955             win32api
.CloseHandle(self
._hThread
) 
 956         except win32api
.error
, ex
: 
 957             raise ProcessError(msg
="Error creating process for '%s': %s"\
 
 961     def wait(self
, timeout
=None):  
 962         """Wait for the started process to complete. 
 964         "timeout" (on Windows) is a floating point number of seconds after 
 965             which to timeout.  Default is win32event.INFINITE. 
 966         "timeout" (on Unix) is akin to the os.waitpid() "options" argument 
 967             (os.WNOHANG may be used to return immediately if the process has 
 968             not exited). Default is 0, i.e. wait forever. 
 970         If the wait time's out it will raise a ProcessError. Otherwise it 
 971         will return the child's exit value (on Windows) or the child's exit 
 972         status excoded as per os.waitpid() (on Linux): 
 973             "a 16-bit number, whose low byte is the signal number that killed 
 974             the process, and whose high byte is the exit status (if the 
 975             signal number is zero); the high bit of the low byte is set if a 
 976             core file was produced." 
 977         In the latter case, use the os.W*() methods to interpret the return 
 980         # XXX Or should returning the exit value be move out to another 
 981         #     function as on Win32 process control? If so, then should 
 982         #     perhaps not make WaitForSingleObject semantic transformation. 
 983         if sys
.platform
.startswith("win"): 
 985                 timeout 
= win32event
.INFINITE
 
 987                 timeout 
= timeout 
* 1000.0 # Win32 API's timeout is in millisecs 
 989             rc 
= win32event
.WaitForSingleObject(self
._hProcess
, timeout
) 
 990             if rc 
== win32event
.WAIT_FAILED
: 
 991                 raise ProcessError("'WAIT_FAILED' when waiting for process to "\
 
 992                                    "terminate: %r" % self
._cmd
, rc
) 
 993             elif rc 
== win32event
.WAIT_TIMEOUT
: 
 994                 raise ProcessError("'WAIT_TIMEOUT' when waiting for process to "\
 
 995                                    "terminate: %r" % self
._cmd
, rc
) 
 997             retval 
= win32process
.GetExitCodeProcess(self
._hProcess
) 
 999             # os.waitpid() will raise: 
1000             #       OSError: [Errno 10] No child processes 
1001             # on subsequent .wait() calls. Change these semantics to have 
1002             # subsequent .wait() calls return the exit status and return 
1003             # immediately without raising an exception. 
1004             # (XXX It would require synchronization code to handle the case 
1005             # of multiple simultaneous .wait() requests, however we can punt 
1006             # on that because it is moot while Linux still has the problem 
1007             # for which _ThreadFixer() exists.) 
1008             if self
.__retvalCache 
is not None: 
1009                 retval 
= self
.__retvalCache
 
1013                 pid
, sts 
= os
.waitpid(self
._pid
, timeout
) 
1014                 if pid 
== self
._pid
: 
1015                     self
.__retvalCache 
= retval 
= sts
 
1017                     raise ProcessError("Wait for process timed out.", 
1021     def kill(self
, exitCode
=0, gracePeriod
=1.0, sig
=None): 
1024         "exitCode" [deprecated, not supported] (Windows only) is the 
1025             code the terminated process should exit with. 
1026         "gracePeriod" (Windows only) is a number of seconds the process is 
1027             allowed to shutdown with a WM_CLOSE signal before a hard 
1028             terminate is called. 
1029         "sig" (Unix only) is the signal to use to kill the process. Defaults 
1030             to signal.SIGKILL. See os.kill() for more information. 
1033             Try for an orderly shutdown via WM_CLOSE.  If still running 
1034             after gracePeriod (1 sec. default), terminate. 
1036         if sys
.platform
.startswith("win"): 
1038             # Send WM_CLOSE to windows in this process group. 
1039             win32gui
.EnumWindows(self
._close
_, 0) 
1041             # Send Ctrl-Break signal to all processes attached to this 
1042             # console. This is supposed to trigger shutdown handlers in 
1043             # each of the processes. 
1045                 win32api
.GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT
, 
1047             except AttributeError: 
1048                 log
.warn("The win32api module does not have "\
 
1049                          "GenerateConsoleCtrlEvent(). This may mean that "\
 
1050                          "parts of this process group have NOT been killed.") 
1051             except win32api
.error
, ex
: 
1052                 if ex
.args
[0] not in (6, 87): 
1053                     # Ignore the following: 
1054                     #   api_error: (87, 'GenerateConsoleCtrlEvent', 'The parameter is incorrect.') 
1055                     #   api_error: (6, 'GenerateConsoleCtrlEvent', 'The handle is invalid.') 
1056                     # Get error 6 if there is no console. 
1059             # Last resort: call TerminateProcess if it has not yet. 
1062                 self
.wait(gracePeriod
) 
1063             except ProcessError
, ex
: 
1064                 log
.info("[%s] Process.kill: calling TerminateProcess", id(self
)) 
1065                 win32process
.TerminateProcess(self
._hProcess
, -1) 
1066                 win32api
.Sleep(100) # wait for resources to be released 
1070                 sig 
= signal
.SIGKILL
 
1072                 os
.kill(self
._pid
, sig
) 
1075                     # Ignore:   OSError: [Errno 3] No such process 
1078     def _close_(self
, hwnd
, dummy
): 
1079         """Callback used by .kill() on Windows. 
1081         EnumWindows callback - sends WM_CLOSE to any window owned by this 
1084         threadId
, processId 
= win32process
.GetWindowThreadProcessId(hwnd
) 
1085         if processId 
== self
._processId
: 
1087             win32gui
.PostMessage(hwnd
, WM_CLOSE
, 0, 0) 
1090 class ProcessOpen(Process
): 
1091     """Create a process and setup pipes to it standard handles. 
1093     This is a super popen3. 
1096     #   - Share some implementation with Process and ProcessProxy. 
1099     def __init__(self
, cmd
, mode
='t', cwd
=None, env
=None): 
1100         """Create a Process with proxy threads for each std handle. 
1102         "cmd" is the command string or argument vector to run. 
1103         "mode" (Windows only) specifies whether the pipes used to communicate 
1104             with the child are openned in text, 't', or binary, 'b', mode. 
1105             This is ignored on platforms other than Windows. Default is 't'. 
1106         "cwd" optionally specifies the directory in which the child process 
1107             should be started. Default is None, a.k.a. inherits the cwd from 
1109         "env" is optionally a mapping specifying the environment in which to 
1110             start the child. Default is None, a.k.a. inherits the environment 
1113         # Keep a reference to ensure it is around for this object's destruction. 
1115         log
.info("ProcessOpen.__init__(cmd=%r, mode=%r, cwd=%r, env=%r)", 
1116                  cmd
, mode
, cwd
, env
) 
1119             raise ProcessError("You must specify a command.") 
1123         if self
._mode 
not in ('t', 'b'): 
1124             raise ProcessError("'mode' must be 't' or 'b'.") 
1127         if sys
.platform
.startswith("win"): 
1128             self
._startOnWindows
() 
1130             self
.__retvalCache 
= None 
1133         _registerProcess(self
) 
1136         #XXX Should probably not rely upon this. 
1137         logres
.info("[%s] ProcessOpen.__del__()", id(self
)) 
1139         del self
.__log 
# drop reference 
1142         if not self
._closed
: 
1143             self
.__log
.info("[%s] ProcessOpen.close()" % id(self
)) 
1145             # Ensure that all IOBuffer's are closed. If they are not, these 
1148                 self
.__log
.info("[%s] ProcessOpen: closing stdin (%r)."\
 
1149                                 % (id(self
), self
.stdin
)) 
1151             except AttributeError: 
1152                 # May not have gotten far enough in the __init__ to set 
1156                 self
.__log
.info("[%s] ProcessOpen: closing stdout (%r)."\
 
1157                                 % (id(self
), self
.stdout
)) 
1159             except AttributeError: 
1160                 # May not have gotten far enough in the __init__ to set 
1164                 self
.__log
.info("[%s] ProcessOpen: closing stderr (%r)."\
 
1165                                 % (id(self
), self
.stderr
)) 
1167             except AttributeError: 
1168                 # May not have gotten far enough in the __init__ to set 
1174     def _forkAndExecChildOnUnix(self
, fdChildStdinRd
, fdChildStdoutWr
, 
1176         """Fork and start the child process. 
1178         Sets self._pid as a side effect. 
1181         if pid 
== 0: # child 
1182             os
.dup2(fdChildStdinRd
, 0) 
1183             os
.dup2(fdChildStdoutWr
, 1) 
1184             os
.dup2(fdChildStderrWr
, 2) 
1185             self
._runChildOnUnix
() 
1189     def _startOnUnix(self
): 
1190         # Create pipes for std handles. 
1191         fdChildStdinRd
, fdChildStdinWr 
= os
.pipe() 
1192         fdChildStdoutRd
, fdChildStdoutWr 
= os
.pipe() 
1193         fdChildStderrRd
, fdChildStderrWr 
= os
.pipe() 
1196             oldDir 
= os
.getcwd() 
1200                 raise ProcessError(msg
=str(ex
), errno
=ex
.errno
) 
1201         self
._forkAndExecChildOnUnix
(fdChildStdinRd
, fdChildStdoutWr
, 
1206         os
.close(fdChildStdinRd
) 
1207         os
.close(fdChildStdoutWr
) 
1208         os
.close(fdChildStderrWr
) 
1210         self
.stdin 
= _FileWrapper(descriptor
=fdChildStdinWr
) 
1211         logres
.info("[%s] ProcessOpen._start(): create child stdin: %r", 
1212                     id(self
), self
.stdin
) 
1213         self
.stdout 
= _FileWrapper(descriptor
=fdChildStdoutRd
) 
1214         logres
.info("[%s] ProcessOpen._start(): create child stdout: %r", 
1215                     id(self
), self
.stdout
) 
1216         self
.stderr 
= _FileWrapper(descriptor
=fdChildStderrRd
) 
1217         logres
.info("[%s] ProcessOpen._start(): create child stderr: %r", 
1218                     id(self
), self
.stderr
) 
1220     def _startOnWindows(self
): 
1221         if type(self
._cmd
) in (types
.ListType
, types
.TupleType
): 
1222             # An arg vector was passed in. 
1223             cmd 
= _joinArgv(self
._cmd
) 
1227         # Create pipes for std handles. 
1228         # (Set the bInheritHandle flag so pipe handles are inherited.) 
1229         saAttr 
= pywintypes
.SECURITY_ATTRIBUTES() 
1230         saAttr
.bInheritHandle 
= 1 
1231         #XXX Should maybe try with os.pipe. Dunno what that does for 
1232         #    inheritability though. 
1233         hChildStdinRd
, hChildStdinWr 
= win32pipe
.CreatePipe(saAttr
, 0)  
1234         hChildStdoutRd
, hChildStdoutWr 
= win32pipe
.CreatePipe(saAttr
, 0)  
1235         hChildStderrRd
, hChildStderrWr 
= win32pipe
.CreatePipe(saAttr
, 0)  
1238             # Duplicate the parent ends of the pipes so they are not 
1240             hChildStdinWrDup 
= win32api
.DuplicateHandle( 
1241                 win32api
.GetCurrentProcess(), 
1243                 win32api
.GetCurrentProcess(), 
1246                 DUPLICATE_SAME_ACCESS
) 
1247             win32api
.CloseHandle(hChildStdinWr
) 
1248             self
._hChildStdinWr 
= hChildStdinWrDup
 
1249             hChildStdoutRdDup 
= win32api
.DuplicateHandle( 
1250                 win32api
.GetCurrentProcess(), 
1252                 win32api
.GetCurrentProcess(), 
1255                 DUPLICATE_SAME_ACCESS
) 
1256             win32api
.CloseHandle(hChildStdoutRd
) 
1257             self
._hChildStdoutRd 
= hChildStdoutRdDup
 
1258             hChildStderrRdDup 
= win32api
.DuplicateHandle( 
1259                 win32api
.GetCurrentProcess(), 
1261                 win32api
.GetCurrentProcess(), 
1264                 DUPLICATE_SAME_ACCESS
) 
1265             win32api
.CloseHandle(hChildStderrRd
) 
1266             self
._hChildStderrRd 
= hChildStderrRdDup
 
1268             # Set the translation mode and buffering. 
1269             if self
._mode 
== 't': 
1273             fdChildStdinWr 
= msvcrt
.open_osfhandle(self
._hChildStdinWr
, flags
) 
1274             fdChildStdoutRd 
= msvcrt
.open_osfhandle(self
._hChildStdoutRd
, flags
) 
1275             fdChildStderrRd 
= msvcrt
.open_osfhandle(self
._hChildStderrRd
, flags
) 
1277             self
.stdin 
= _FileWrapper(descriptor
=fdChildStdinWr
, 
1278                                       handle
=self
._hChildStdinWr
) 
1279             logres
.info("[%s] ProcessOpen._start(): create child stdin: %r", 
1280                         id(self
), self
.stdin
) 
1281             self
.stdout 
= _FileWrapper(descriptor
=fdChildStdoutRd
, 
1282                                        handle
=self
._hChildStdoutRd
) 
1283             logres
.info("[%s] ProcessOpen._start(): create child stdout: %r", 
1284                         id(self
), self
.stdout
) 
1285             self
.stderr 
= _FileWrapper(descriptor
=fdChildStderrRd
, 
1286                                        handle
=self
._hChildStderrRd
) 
1287             logres
.info("[%s] ProcessOpen._start(): create child stderr: %r", 
1288                         id(self
), self
.stderr
) 
1290             # Start the child process. 
1291             si 
= win32process
.STARTUPINFO()  
1292             si
.dwFlags 
= win32process
.STARTF_USESHOWWINDOW
 
1293             si
.wShowWindow 
= 0 # SW_HIDE 
1294             si
.hStdInput 
= hChildStdinRd
 
1295             si
.hStdOutput 
= hChildStdoutWr
 
1296             si
.hStdError 
= hChildStderrWr
 
1297             si
.dwFlags |
= win32process
.STARTF_USESTDHANDLES
 
1299             cmd 
= _fixupCommand(cmd
, self
._env
) 
1301             creationFlags 
= win32process
.CREATE_NEW_PROCESS_GROUP
 
1303                 self
._hProcess
, hThread
, self
._processId
, threadId\
 
1304                     = _SaferCreateProcess( 
1307                         None,           # process security attributes  
1308                         None,           # primary thread security attributes  
1309                         1,              # handles are inherited  
1310                         creationFlags
,  # creation flags  
1311                         self
._env
,      # environment 
1312                         self
._cwd
,      # current working directory 
1313                         si
)             # STARTUPINFO pointer  
1314             except win32api
.error
, ex
: 
1315                 raise ProcessError(msg
=ex
.args
[2], errno
=ex
.args
[0]) 
1316             win32api
.CloseHandle(hThread
) 
1319             # Close child ends of pipes on the parent's side (the 
1320             # parent's ends of the pipe are closed in the _FileWrappers.) 
1321             win32file
.CloseHandle(hChildStdinRd
) 
1322             win32file
.CloseHandle(hChildStdoutWr
) 
1323             win32file
.CloseHandle(hChildStderrWr
) 
1325     def wait(self
, timeout
=None):  
1326         """Wait for the started process to complete. 
1328         "timeout" (on Windows) is a floating point number of seconds after 
1329             which to timeout.  Default is win32event.INFINITE. 
1330         "timeout" (on Unix) is akin to the os.waitpid() "options" argument 
1331             (os.WNOHANG may be used to return immediately if the process has 
1332             not exited). Default is 0, i.e. wait forever. 
1334         If the wait time's out it will raise a ProcessError. Otherwise it 
1335         will return the child's exit value (on Windows) or the child's exit 
1336         status excoded as per os.waitpid() (on Linux): 
1337             "a 16-bit number, whose low byte is the signal number that killed 
1338             the process, and whose high byte is the exit status (if the 
1339             signal number is zero); the high bit of the low byte is set if a 
1340             core file was produced." 
1341         In the latter case, use the os.W*() methods to interpret the return 
1344         # XXX Or should returning the exit value be move out to another 
1345         #    function as on Win32 process control? If so, then should 
1346         #    perhaps not make WaitForSingleObject semantic 
1349         #   - Need to rationalize the .wait() API for Windows vs. Unix. 
1350         #     It is a real pain in the current situation. 
1351         if sys
.platform
.startswith("win"): 
1353                 timeout 
= win32event
.INFINITE
 
1355                 timeout 
= timeout 
* 1000.0 # Win32 API's timeout is in millisecs 
1357             #rc = win32event.WaitForSingleObject(self._hProcess, timeout) 
1358             rc 
= win32event
.WaitForSingleObject(self
._hProcess
, int(timeout
)) # MATT -- Making timeout an integer 
1359             if rc 
== win32event
.WAIT_FAILED
: 
1360                 raise ProcessError("'WAIT_FAILED' when waiting for process to "\
 
1361                                    "terminate: %r" % self
._cmd
, rc
) 
1362             elif rc 
== win32event
.WAIT_TIMEOUT
: 
1363                 raise ProcessError("'WAIT_TIMEOUT' when waiting for process to "\
 
1364                                    "terminate: %r" % self
._cmd
, rc
) 
1366             retval 
= win32process
.GetExitCodeProcess(self
._hProcess
) 
1368             # os.waitpid() will raise: 
1369             #       OSError: [Errno 10] No child processes 
1370             # on subsequent .wait() calls. Change these semantics to have 
1371             # subsequent .wait() calls return the exit status and return 
1372             # immediately without raising an exception. 
1373             # (XXX It would require synchronization code to handle the case 
1374             # of multiple simultaneous .wait() requests, however we can punt 
1375             # on that because it is moot while Linux still has the problem 
1376             # for which _ThreadFixer() exists.) 
1377             if self
.__retvalCache 
is not None: 
1378                 retval 
= self
.__retvalCache
 
1382                 pid
, sts 
= os
.waitpid(self
._pid
, timeout
) 
1383                 if pid 
== self
._pid
: 
1384                     self
.__retvalCache 
= retval 
= sts
 
1386                     raise ProcessError("Wait for process timed out.", 
1388         _unregisterProcess(self
) 
1391     def kill(self
, exitCode
=0, gracePeriod
=1.0, sig
=None): 
1394         "exitCode" [deprecated, not supported] (Windows only) is the 
1395             code the terminated process should exit with. 
1396         "gracePeriod" (Windows only) is a number of seconds the process is 
1397             allowed to shutdown with a WM_CLOSE signal before a hard 
1398             terminate is called. 
1399         "sig" (Unix only) is the signal to use to kill the process. Defaults 
1400             to signal.SIGKILL. See os.kill() for more information. 
1403             Try for an orderly shutdown via WM_CLOSE.  If still running 
1404             after gracePeriod (1 sec. default), terminate. 
1406         if sys
.platform
.startswith("win"): 
1408             # Send WM_CLOSE to windows in this process group. 
1409             win32gui
.EnumWindows(self
._close
_, 0) 
1411             # Send Ctrl-Break signal to all processes attached to this 
1412             # console. This is supposed to trigger shutdown handlers in 
1413             # each of the processes. 
1415                 win32api
.GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT
, 
1417             except AttributeError: 
1418                 log
.warn("The win32api module does not have "\
 
1419                          "GenerateConsoleCtrlEvent(). This may mean that "\
 
1420                          "parts of this process group have NOT been killed.") 
1421             except win32api
.error
, ex
: 
1422                 if ex
.args
[0] not in (6, 87): 
1423                     # Ignore the following: 
1424                     #   api_error: (87, 'GenerateConsoleCtrlEvent', 'The parameter is incorrect.') 
1425                     #   api_error: (6, 'GenerateConsoleCtrlEvent', 'The handle is invalid.') 
1426                     # Get error 6 if there is no console. 
1429             # Last resort: call TerminateProcess if it has not yet. 
1432                 self
.wait(gracePeriod
) 
1433             except ProcessError
, ex
: 
1434                 log
.info("[%s] Process.kill: calling TerminateProcess", id(self
)) 
1435                 win32process
.TerminateProcess(self
._hProcess
, -1) 
1436                 win32api
.Sleep(100) # wait for resources to be released 
1440                 sig 
= signal
.SIGKILL
 
1442                 os
.kill(self
._pid
, sig
) 
1445                     # Ignore:   OSError: [Errno 3] No such process 
1448         _unregisterProcess(self
) 
1450     def _close_(self
, hwnd
, dummy
): 
1451         """Callback used by .kill() on Windows. 
1453         EnumWindows callback - sends WM_CLOSE to any window owned by this 
1456         threadId
, processId 
= win32process
.GetWindowThreadProcessId(hwnd
) 
1457         if processId 
== self
._processId
: 
1459             win32gui
.PostMessage(hwnd
, WM_CLOSE
, 0, 0) 
1462 class ProcessProxy(Process
): 
1463     """Create a process and proxy communication via the standard handles. 
1465     #XXX To add to docstring: 
1466     #   - stdout/stderr proxy handling 
1467     #   - stdin proxy handling 
1469     #   - how to .start(), i.e. basic usage rules 
1470     #   - mention that pased in stdin/stdout/stderr objects have to 
1471     #     implement at least .write (is .write correct for stdin)? 
1472     #   - if you pass in stdin, stdout, and/or stderr streams it is the 
1473     #     user's responsibility to close them afterwards. 
1474     #   - 'cmd' arg can be a command string or an arg vector 
1477     #   - .suspend() and .resume()? See Win32::Process Perl module. 
1479     def __init__(self
, cmd
, mode
='t', cwd
=None, env
=None, 
1480                  stdin
=None, stdout
=None, stderr
=None): 
1481         """Create a Process with proxy threads for each std handle. 
1483         "cmd" is the command string or argument vector to run. 
1484         "mode" (Windows only) specifies whether the pipes used to communicate 
1485             with the child are openned in text, 't', or binary, 'b', mode. 
1486             This is ignored on platforms other than Windows. Default is 't'. 
1487         "cwd" optionally specifies the directory in which the child process 
1488             should be started. Default is None, a.k.a. inherits the cwd from 
1490         "env" is optionally a mapping specifying the environment in which to 
1491             start the child. Default is None, a.k.a. inherits the environment 
1493         "stdin", "stdout", "stderr" can be used to specify objects with 
1494             file-like interfaces to handle read (stdout/stderr) and write 
1495             (stdin) events from the child. By default a process.IOBuffer 
1496             instance is assigned to each handler. IOBuffer may be 
1497             sub-classed. See the IOBuffer doc string for more information. 
1499         # Keep a reference to ensure it is around for this object's destruction. 
1501         log
.info("ProcessProxy.__init__(cmd=%r, mode=%r, cwd=%r, env=%r, "\
 
1502                  "stdin=%r, stdout=%r, stderr=%r)", 
1503                  cmd
, mode
, cwd
, env
, stdin
, stdout
, stderr
) 
1506             raise ProcessError("You must specify a command.") 
1508         if self
._mode 
not in ('t', 'b'): 
1509             raise ProcessError("'mode' must be 't' or 'b'.") 
1513             self
.stdin 
= IOBuffer(name
='<stdin>') 
1517             self
.stdout 
= IOBuffer(name
='<stdout>') 
1519             self
.stdout 
= stdout
 
1521             self
.stderr 
= IOBuffer(name
='<stderr>') 
1523             self
.stderr 
= stderr
 
1526         if sys
.platform
.startswith("win"): 
1527             self
._startOnWindows
() 
1529             self
.__retvalCache 
= None 
1532         _registerProcess(self
) 
1535         #XXX Should probably not rely upon this. 
1536         logres
.info("[%s] ProcessProxy.__del__()", id(self
)) 
1538         del self
.__log 
# drop reference 
1541         if not self
._closed
: 
1542             self
.__log
.info("[%s] ProcessProxy.close()" % id(self
)) 
1544             # Ensure that all IOBuffer's are closed. If they are not, these 
1546             self
.__log
.info("[%s] ProcessProxy: closing stdin (%r)."\
 
1547                             % (id(self
), self
.stdin
)) 
1550                 self
._stdinProxy
.join() 
1551             except AttributeError: 
1552                 # May not have gotten far enough in the __init__ to set 
1555             self
.__log
.info("[%s] ProcessProxy: closing stdout (%r)."\
 
1556                             % (id(self
), self
.stdout
)) 
1559                 if self
._stdoutProxy 
is not threading
.currentThread(): 
1560                     self
._stdoutProxy
.join() 
1561             except AttributeError: 
1562                 # May not have gotten far enough in the __init__ to set 
1565             self
.__log
.info("[%s] ProcessProxy: closing stderr (%r)."\
 
1566                             % (id(self
), self
.stderr
)) 
1569                 if self
._stderrProxy 
is not threading
.currentThread(): 
1570                     self
._stderrProxy
.join() 
1571             except AttributeError: 
1572                 # May not have gotten far enough in the __init__ to set 
1578     def _forkAndExecChildOnUnix(self
, fdChildStdinRd
, fdChildStdoutWr
, 
1580         """Fork and start the child process. 
1582         Sets self._pid as a side effect. 
1585         if pid 
== 0: # child 
1586             os
.dup2(fdChildStdinRd
, 0) 
1587             os
.dup2(fdChildStdoutWr
, 1) 
1588             os
.dup2(fdChildStderrWr
, 2) 
1589             self
._runChildOnUnix
() 
1593     def _startOnUnix(self
): 
1594         # Create pipes for std handles. 
1595         fdChildStdinRd
, fdChildStdinWr 
= os
.pipe() 
1596         fdChildStdoutRd
, fdChildStdoutWr 
= os
.pipe() 
1597         fdChildStderrRd
, fdChildStderrWr 
= os
.pipe() 
1600             oldDir 
= os
.getcwd() 
1604                 raise ProcessError(msg
=str(ex
), errno
=ex
.errno
) 
1605         self
._forkAndExecChildOnUnix
(fdChildStdinRd
, fdChildStdoutWr
, 
1610         os
.close(fdChildStdinRd
) 
1611         os
.close(fdChildStdoutWr
) 
1612         os
.close(fdChildStderrWr
) 
1614         childStdin 
= _FileWrapper(descriptor
=fdChildStdinWr
) 
1615         logres
.info("[%s] ProcessProxy._start(): create child stdin: %r", 
1616                     id(self
), childStdin
) 
1617         childStdout 
= _FileWrapper(descriptor
=fdChildStdoutRd
) 
1618         logres
.info("[%s] ProcessProxy._start(): create child stdout: %r", 
1619                     id(self
), childStdout
) 
1620         childStderr 
= _FileWrapper(descriptor
=fdChildStderrRd
) 
1621         logres
.info("[%s] ProcessProxy._start(): create child stderr: %r", 
1622                     id(self
), childStderr
) 
1624         # Create proxy threads for the out pipes. 
1625         self
._stdinProxy 
= _InFileProxy(self
.stdin
, childStdin
, name
='<stdin>') 
1626         self
._stdinProxy
.start() 
1627         # Clean up the parent's side of <stdin> when it is observed that 
1628         # the child has closed its side of <stdout> and <stderr>. (This 
1629         # is one way of determining when it is appropriate to clean up 
1630         # this pipe, with compromises. See the discussion at the top of 
1632         closer 
= _CountingCloser([self
.stdin
, childStdin
, self
], 2) 
1633         self
._stdoutProxy 
= _OutFileProxy(childStdout
, self
.stdout
,  
1636         self
._stdoutProxy
.start() 
1637         self
._stderrProxy 
= _OutFileProxy(childStderr
, self
.stderr
, 
1640         self
._stderrProxy
.start() 
1642     def _startOnWindows(self
): 
1643         if type(self
._cmd
) in (types
.ListType
, types
.TupleType
): 
1644             # An arg vector was passed in. 
1645             cmd 
= _joinArgv(self
._cmd
) 
1649         # Create pipes for std handles. 
1650         # (Set the bInheritHandle flag so pipe handles are inherited.) 
1651         saAttr 
= pywintypes
.SECURITY_ATTRIBUTES() 
1652         saAttr
.bInheritHandle 
= 1 
1653         #XXX Should maybe try with os.pipe. Dunno what that does for 
1654         #    inheritability though. 
1655         hChildStdinRd
, hChildStdinWr 
= win32pipe
.CreatePipe(saAttr
, 0)  
1656         hChildStdoutRd
, hChildStdoutWr 
= win32pipe
.CreatePipe(saAttr
, 0)  
1657         hChildStderrRd
, hChildStderrWr 
= win32pipe
.CreatePipe(saAttr
, 0)  
1660             # Duplicate the parent ends of the pipes so they are not 
1662             hChildStdinWrDup 
= win32api
.DuplicateHandle( 
1663                 win32api
.GetCurrentProcess(), 
1665                 win32api
.GetCurrentProcess(), 
1668                 DUPLICATE_SAME_ACCESS
) 
1669             win32api
.CloseHandle(hChildStdinWr
) 
1670             self
._hChildStdinWr 
= hChildStdinWrDup
 
1671             hChildStdoutRdDup 
= win32api
.DuplicateHandle( 
1672                 win32api
.GetCurrentProcess(), 
1674                 win32api
.GetCurrentProcess(), 
1677                 DUPLICATE_SAME_ACCESS
) 
1678             win32api
.CloseHandle(hChildStdoutRd
) 
1679             self
._hChildStdoutRd 
= hChildStdoutRdDup
 
1680             hChildStderrRdDup 
= win32api
.DuplicateHandle( 
1681                 win32api
.GetCurrentProcess(), 
1683                 win32api
.GetCurrentProcess(), 
1686                 DUPLICATE_SAME_ACCESS
) 
1687             win32api
.CloseHandle(hChildStderrRd
) 
1688             self
._hChildStderrRd 
= hChildStderrRdDup
 
1690             # Set the translation mode. 
1691             if self
._mode 
== 't': 
1697             fdChildStdinWr 
= msvcrt
.open_osfhandle(self
._hChildStdinWr
, flags
) 
1698             fdChildStdoutRd 
= msvcrt
.open_osfhandle(self
._hChildStdoutRd
, flags
) 
1699             fdChildStderrRd 
= msvcrt
.open_osfhandle(self
._hChildStderrRd
, flags
) 
1701             childStdin 
= _FileWrapper(descriptor
=fdChildStdinWr
, 
1702                                       handle
=self
._hChildStdinWr
) 
1703             logres
.info("[%s] ProcessProxy._start(): create child stdin: %r", 
1704                         id(self
), childStdin
) 
1705             childStdout 
= _FileWrapper(descriptor
=fdChildStdoutRd
, 
1706                                        handle
=self
._hChildStdoutRd
) 
1707             logres
.info("[%s] ProcessProxy._start(): create child stdout: %r", 
1708                         id(self
), childStdout
) 
1709             childStderr 
= _FileWrapper(descriptor
=fdChildStderrRd
, 
1710                                        handle
=self
._hChildStderrRd
) 
1711             logres
.info("[%s] ProcessProxy._start(): create child stderr: %r", 
1712                         id(self
), childStderr
) 
1714             # Start the child process. 
1715             si 
= win32process
.STARTUPINFO()  
1716             si
.dwFlags 
= win32process
.STARTF_USESHOWWINDOW
 
1717             si
.wShowWindow 
= 0 # SW_HIDE 
1718             si
.hStdInput 
= hChildStdinRd
 
1719             si
.hStdOutput 
= hChildStdoutWr
 
1720             si
.hStdError 
= hChildStderrWr
 
1721             si
.dwFlags |
= win32process
.STARTF_USESTDHANDLES
 
1723             cmd 
= _fixupCommand(cmd
, self
._env
) 
1724             log
.debug("cmd = %r", cmd
) 
1726             creationFlags 
= win32process
.CREATE_NEW_PROCESS_GROUP
 
1728                 self
._hProcess
, hThread
, self
._processId
, threadId\
 
1729                     = _SaferCreateProcess( 
1732                         None,           # process security attributes  
1733                         None,           # primary thread security attributes  
1734                         1,              # handles are inherited  
1735                         creationFlags
,  # creation flags  
1736                         self
._env
,      # environment 
1737                         self
._cwd
,      # current working directory 
1738                         si
)             # STARTUPINFO pointer  
1739             except win32api
.error
, ex
: 
1740                 raise ProcessError(msg
=ex
.args
[2], errno
=ex
.args
[0]) 
1741             win32api
.CloseHandle(hThread
) 
1744             # Close child ends of pipes on the parent's side (the 
1745             # parent's ends of the pipe are closed in the _FileWrappers.) 
1746             win32file
.CloseHandle(hChildStdinRd
) 
1747             win32file
.CloseHandle(hChildStdoutWr
) 
1748             win32file
.CloseHandle(hChildStderrWr
) 
1750         # Create proxy threads for the pipes. 
1751         self
._stdinProxy 
= _InFileProxy(self
.stdin
, childStdin
, name
='<stdin>') 
1752         self
._stdinProxy
.start() 
1753         # Clean up the parent's side of <stdin> when it is observed that 
1754         # the child has closed its side of <stdout>. (This is one way of 
1755         # determining when it is appropriate to clean up this pipe, with 
1756         # compromises. See the discussion at the top of this module.) 
1757         self
._stdoutProxy 
= _OutFileProxy(childStdout
, self
.stdout
,  
1758                                           [self
.stdin
, childStdin
, self
], 
1760         self
._stdoutProxy
.start() 
1761         self
._stderrProxy 
= _OutFileProxy(childStderr
, self
.stderr
, 
1763         self
._stderrProxy
.start() 
1765     def wait(self
, timeout
=None):  
1766         """Wait for the started process to complete. 
1768         "timeout" (on Windows) is a floating point number of seconds after 
1769             which to timeout.  Default is win32event.INFINITE. 
1770         "timeout" (on Unix) is akin to the os.waitpid() "options" argument 
1771             (os.WNOHANG may be used to return immediately if the process has 
1772             not exited). Default is 0, i.e. wait forever. 
1774         If the wait time's out it will raise a ProcessError. Otherwise it 
1775         will return the child's exit value (on Windows) or the child's exit 
1776         status excoded as per os.waitpid() (on Linux): 
1777             "a 16-bit number, whose low byte is the signal number that killed 
1778             the process, and whose high byte is the exit status (if the 
1779             signal number is zero); the high bit of the low byte is set if a 
1780             core file was produced." 
1781         In the latter case, use the os.W*() methods to interpret the return 
1784         # XXX Or should returning the exit value be move out to another 
1785         #     function as on Win32 process control? If so, then should 
1786         #     perhaps not make WaitForSingleObject semantic transformation. 
1787         if sys
.platform
.startswith("win"): 
1789                 timeout 
= win32event
.INFINITE
 
1791                 timeout 
= timeout 
* 1000.0 # Win32 API's timeout is in millisecs 
1793             rc 
= win32event
.WaitForSingleObject(self
._hProcess
, timeout
) 
1794             if rc 
== win32event
.WAIT_FAILED
: 
1795                 raise ProcessError("'WAIT_FAILED' when waiting for process to "\
 
1796                                    "terminate: %r" % self
._cmd
, rc
) 
1797             elif rc 
== win32event
.WAIT_TIMEOUT
: 
1798                 raise ProcessError("'WAIT_TIMEOUT' when waiting for process to "\
 
1799                                    "terminate: %r" % self
._cmd
, rc
) 
1801             retval 
= win32process
.GetExitCodeProcess(self
._hProcess
) 
1803             # os.waitpid() will raise: 
1804             #       OSError: [Errno 10] No child processes 
1805             # on subsequent .wait() calls. Change these semantics to have 
1806             # subsequent .wait() calls return the exit status and return 
1807             # immediately without raising an exception. 
1808             # (XXX It would require synchronization code to handle the case 
1809             # of multiple simultaneous .wait() requests, however we can punt 
1810             # on that because it is moot while Linux still has the problem 
1811             # for which _ThreadFixer() exists.) 
1812             if self
.__retvalCache 
is not None: 
1813                 retval 
= self
.__retvalCache
 
1817                 pid
, sts 
= os
.waitpid(self
._pid
, timeout
) 
1818                 if pid 
== self
._pid
: 
1819                     self
.__retvalCache 
= retval 
= sts
 
1821                     raise ProcessError("Wait for process timed out.", 
1823         _unregisterProcess(self
) 
1826     def kill(self
, exitCode
=0, gracePeriod
=1.0, sig
=None): 
1829         "exitCode" [deprecated, not supported] (Windows only) is the 
1830             code the terminated process should exit with. 
1831         "gracePeriod" (Windows only) is a number of seconds the process is 
1832             allowed to shutdown with a WM_CLOSE signal before a hard 
1833             terminate is called. 
1834         "sig" (Unix only) is the signal to use to kill the process. Defaults 
1835             to signal.SIGKILL. See os.kill() for more information. 
1838             Try for an orderly shutdown via WM_CLOSE.  If still running 
1839             after gracePeriod (1 sec. default), terminate. 
1841         if sys
.platform
.startswith("win"): 
1843             # Send WM_CLOSE to windows in this process group. 
1844             win32gui
.EnumWindows(self
._close
_, 0) 
1846             # Send Ctrl-Break signal to all processes attached to this 
1847             # console. This is supposed to trigger shutdown handlers in 
1848             # each of the processes. 
1850                 win32api
.GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT
, 
1852             except AttributeError: 
1853                 log
.warn("The win32api module does not have "\
 
1854                          "GenerateConsoleCtrlEvent(). This may mean that "\
 
1855                          "parts of this process group have NOT been killed.") 
1856             except win32api
.error
, ex
: 
1857                 if ex
.args
[0] not in (6, 87): 
1858                     # Ignore the following: 
1859                     #   api_error: (87, 'GenerateConsoleCtrlEvent', 'The parameter is incorrect.') 
1860                     #   api_error: (6, 'GenerateConsoleCtrlEvent', 'The handle is invalid.') 
1861                     # Get error 6 if there is no console. 
1864             # Last resort: call TerminateProcess if it has not yet. 
1867                 self
.wait(gracePeriod
) 
1868             except ProcessError
, ex
: 
1869                 log
.info("[%s] Process.kill: calling TerminateProcess", id(self
)) 
1870                 win32process
.TerminateProcess(self
._hProcess
, -1) 
1871                 win32api
.Sleep(100) # wait for resources to be released 
1875                 sig 
= signal
.SIGKILL
 
1877                 os
.kill(self
._pid
, sig
) 
1880                     # Ignore:   OSError: [Errno 3] No such process 
1883         _unregisterProcess(self
) 
1885     def _close_(self
, hwnd
, dummy
): 
1886         """Callback used by .kill() on Windows. 
1888         EnumWindows callback - sends WM_CLOSE to any window owned by this 
1891         threadId
, processId 
= win32process
.GetWindowThreadProcessId(hwnd
) 
1892         if processId 
== self
._processId
: 
1894             win32gui
.PostMessage(hwnd
, WM_CLOSE
, 0, 0) 
1898     """Want to be able to both read and write to this buffer from 
1899     difference threads and have the same read/write semantics as for a 
1902     This class is subclass-able. _doRead(), _doWrite(), _doReadline(), 
1903     _doClose(), _haveLine(), and _haveNumBytes() can be overridden for 
1904     specific functionality. The synchronization issues (block on read 
1905     until write provides the needed data, termination) are handled for 
1909         .seek()     # Because we are managing *two* positions (one each 
1910         .tell()     #   for reading and writing), these do not make 
1914     #   - Is performance a problem? This will likely be slower that 
1915     #     StringIO.StringIO(). 
1917     def __init__(self
, mutex
=None, stateChange
=None, name
=None): 
1918         """'name' can be set for debugging, it will be used in log messages.""" 
1919         if name 
is not None: 
1922             self
._name 
= id(self
) 
1923         log
.info("[%s] IOBuffer.__init__()" % self
._name
) 
1926         # A state change is defined as the buffer being closed or a 
1928         if mutex 
is not None: 
1931             self
._mutex 
= threading
.Lock() 
1932         if stateChange 
is not None: 
1933             self
._stateChange 
= stateChange
 
1935             self
._stateChange 
= threading
.Condition() 
1938     def _doWrite(self
, s
): 
1939         self
.__buf 
+= s  
# Append to buffer. 
1942         log
.info("[%s] IOBuffer.write(s=%r)", self
._name
, s
) 
1943         # Silently drop writes after the buffer has been close()'d. 
1946         # If empty write, close buffer (mimicking behaviour from 
1952         self
._mutex
.acquire() 
1954         self
._stateChange
.acquire() 
1955         self
._stateChange
.notifyAll()   # Notify of the write(). 
1956         self
._stateChange
.release() 
1957         self
._mutex
.release() 
1959     def writelines(self
, list): 
1960         self
.write(''.join(list)) 
1962     def _doRead(self
, n
): 
1963         """Pop 'n' bytes from the internal buffer and return them.""" 
1965             idx 
= len(self
.__buf
) 
1967             idx 
= min(n
, len(self
.__buf
)) 
1968         retval
, self
.__buf 
= self
.__buf
[:idx
], self
.__buf
[idx
:] 
1971     def read(self
, n
=-1): 
1972         log
.info("[%s] IOBuffer.read(n=%r)" % (self
._name
, n
)) 
1973         log
.info("[%s] IOBuffer.read(): wait for data" % self
._name
) 
1975             # Wait until the buffer is closed, i.e. no more writes will 
1978                 if self
._closed
: break 
1979                 #log.debug("[%s]     <<< IOBuffer.read: state change .wait()"\ 
1981                 self
._stateChange
.acquire() 
1982                 self
._stateChange
.wait() 
1983                 self
._stateChange
.release() 
1984                 #log.debug("[%s]     >>> IOBuffer.read: done change .wait()"\ 
1987             # Wait until there are the requested number of bytes to read 
1988             # (or until the buffer is closed, i.e. no more writes will 
1990             # XXX WARNING: I *think* there is a race condition around 
1991             #     here whereby self.fparent.read() in _InFileProxy can 
1992             #     hang. *Sometime* test_stdin::test_stdin_buffer() will 
1993             #     hang. This was *before* I moved the 
1994             #     _stateChange.acquire() and .release() calls out side 
1995             #     of the 'while 1:' here. ...and now they are back 
1998                 if self
._closed
: break 
1999                 if self
._haveNumBytes
(n
): break 
2000                 #log.debug("[%s]     <<< IOBuffer.read: state change .wait()"\ 
2002                 self
._stateChange
.acquire() 
2003                 self
._stateChange
.wait() 
2004                 self
._stateChange
.release() 
2005                 #log.debug("[%s]     >>> IOBuffer.read: done change .wait()"\ 
2007         log
.info("[%s] IOBuffer.read(): done waiting for data" % self
._name
) 
2009         self
._mutex
.acquire() 
2010         retval 
= self
._doRead
(n
) 
2011         self
._mutex
.release() 
2014     def _doReadline(self
, n
): 
2015         """Pop the front line (or n bytes of it, whichever is less) from 
2016         the internal buffer and return it. 
2018         idx 
= self
.__buf
.find('\n') 
2020             idx 
= len(self
.__buf
) 
2022             idx 
+= 1 # include the '\n' 
2025         retval
, self
.__buf 
= self
.__buf
[:idx
], self
.__buf
[idx
:] 
2028     def _haveLine(self
): 
2029         return self
.__buf
.find('\n') != -1 
2031     def _haveNumBytes(self
, n
=None): 
2032         return len(self
.__buf
) >= n
 
2034     def readline(self
, n
=None): 
2035         # Wait until there is a full line (or at least 'n' bytes) 
2036         # in the buffer or until the buffer is closed, i.e. no more 
2038         log
.info("[%s] IOBuffer.readline(n=%r)" % (self
._name
, n
)) 
2040         log
.info("[%s] IOBuffer.readline(): wait for data" % self
._name
) 
2042             if self
._closed
: break 
2043             if self
._haveLine
(): break 
2044             if n 
is not None and self
._haveNumBytes
(n
): break 
2045             self
._stateChange
.acquire() 
2046             self
._stateChange
.wait() 
2047             self
._stateChange
.release() 
2048         log
.info("[%s] IOBuffer.readline(): done waiting for data"\
 
2051         self
._mutex
.acquire() 
2052         retval 
= self
._doReadline
(n
) 
2053         self
._mutex
.release() 
2056     def readlines(self
): 
2059             line 
= self
.readline() 
2070         if not self
._closed
: 
2071             log
.info("[%s] IOBuffer.close()" % self
._name
) 
2074             self
._stateChange
.acquire() 
2075             self
._stateChange
.notifyAll()   # Notify of the close(). 
2076             self
._stateChange
.release() 
2079         log
.info("[%s] IOBuffer.flush()" % self
._name
) 
2080         #XXX Perhaps flush() should unwedged possible waiting .read() 
2081         #    and .readline() calls that are waiting for more data??? 
2084 class _InFileProxy(threading
.Thread
): 
2085     """A thread to proxy stdin.write()'s from the parent to the child.""" 
2086     def __init__(self
, fParent
, fChild
, name
=None): 
2088         "fParent" is a Python file-like object setup for writing. 
2089         "fChild" is a Win32 handle to the a child process' output pipe. 
2090         "name" can be set for debugging, it will be used in log messages. 
2092         log
.info("[%s, %s] _InFileProxy.__init__(fChild=%r, fParent=%r)", 
2093                  name
, id(self
), fChild
, fParent
) 
2094         threading
.Thread
.__init
__(self
, name
=name
) 
2095         self
.fChild 
= fChild
 
2096         self
.fParent 
= fParent
 
2099         log
.info("[%s] _InFileProxy: start" % self
.getName()) 
2101             self
._proxyFromParentToChild
() 
2103             log
.info("[%s] _InFileProxy: closing parent (%r)"\
 
2104                      % (self
.getName(), self
.fParent
)) 
2106                 self
.fParent
.close() 
2108                 pass # Ignore: IOError: [Errno 4] Interrupted system call 
2109         log
.info("[%s] _InFileProxy: done" % self
.getName()) 
2111     def _proxyFromParentToChild(self
): 
2113         # Read output from the child process, and (for now) just write 
2116             log
.info("[%s] _InFileProxy: waiting for read on parent (%r)"\
 
2117                      % (self
.getName(), self
.fParent
)) 
2118             # XXX Get hangs here (!) even with 
2119             #     self.stdin.close() in ProcessProxy' __del__() under this 
2121             #           p = ProcessProxy([...], stdin=sys.stdin) 
2122             #     The user must manually send '\n' via <Enter> or EOF 
2123             #     via <Ctrl-Z> to unlock this. How to get around that? 
2124             #     See cleanOnTermination note in _OutFileProxy.run() 
2126             #log.debug("XXX          -> start read on %r" % self.fParent) 
2128                 text 
= self
.fParent
.read(CHUNKSIZE
) 
2129             except ValueError, ex
: 
2130                 # ValueError is raised with trying to write to a closed 
2133             #log.debug("XXX          <- done read on %r" % self.fParent) 
2135                 # Empty text signifies that the pipe has been closed on 
2137                 log
.info("[%s] _InFileProxy: observed close of parent (%r)"\
 
2138                          % (self
.getName(), self
.fParent
)) 
2139                 # Signal the child so it knows to stop listening. 
2141                     logres
.info("[%s] _InFileProxy: closing child after "\
 
2142                                 "observing parent's close: %r", self
.getName(), 
2147                         pass # Ignore: IOError: [Errno 4] Interrupted system call 
2149                     # Ignore: IOError: [Errno 9] Bad file descriptor 
2150                     # XXX Do we *know* we want to do that? 
2154                 log
.info("[%s] _InFileProxy: read %d bytes from parent: %r"\
 
2155                          % (self
.getName(), len(text
), text
)) 
2157             log
.info("[%s, %s] _InFileProxy: writing %r to child (%r)", 
2158                      self
.getName(), id(self
), text
, self
.fChild
) 
2160                 self
.fChild
.write(text
) 
2161             except (OSError, IOError), ex
: 
2162                 # Ignore errors for now. For example: 
2163                 # - Get this on Win9x when writing multiple lines to "dir": 
2164                 #   OSError: [Errno 32] Broken pipe 
2165                 #XXX There *may* be errors we don't want to avoid. 
2166                 #XXX Should maybe just ignore EnvironmentError (base class). 
2167                 log
.info("[%s] _InFileProxy: error writing to child (%r), "\
 
2168                          "closing: %s" % (self
.getName(), self
.fParent
, ex
)) 
2170             log
.info("[%s] _InFileProxy: wrote %d bytes to child: %r"\
 
2171                      % (self
.getName(), len(text
), text
)) 
2174 class _OutFileProxy(threading
.Thread
): 
2175     """A thread to watch an "out" file from the spawned child process 
2176     and pass on write's to the parent. 
2178     def __init__(self
, fChild
, fParent
, toClose
=[], name
=None): 
2180         "fChild" is a Win32 handle to the a child process' output pipe. 
2181         "fParent" is a Python file-like object setup for writing. 
2182         "toClose" is a list of objects on which to call .close when this 
2183             proxy is terminating. 
2184         "name" can be set for debugging, it will be used in log messages. 
2186         log
.info("[%s] _OutFileProxy.__init__(fChild=%r, fParent=%r, "\
 
2187                  "toClose=%r)", name
, fChild
, fParent
, toClose
) 
2188         threading
.Thread
.__init
__(self
, name
=name
) 
2189         self
.fChild 
= fChild
 
2190         self
.fParent 
= fParent
 
2191         self
.toClose 
= toClose
 
2194         log
.info("[%s] _OutFileProxy: start" % self
.getName()) 
2196             self
._proxyFromChildToParent
() 
2198             logres
.info("[%s] _OutFileProxy: terminating, close child (%r)", 
2199                         self
.getName(), self
.fChild
) 
2203                 pass # Ignore: IOError: [Errno 4] Interrupted system call 
2204             log
.info("[%s] _OutFileProxy: closing parent (%r)", 
2205                      self
.getName(), self
.fParent
) 
2207                 self
.fParent
.close() 
2209                 pass # Ignore: IOError: [Errno 4] Interrupted system call 
2211                 logres
.info("[%s] _OutFileProxy: closing %r after "\
 
2212                             "closing parent", self
.getName(), self
.toClose
[0]) 
2214                     self
.toClose
[0].close() 
2216                     pass # Ignore: IOError: [Errno 4] Interrupted system call 
2218         log
.info("[%s] _OutFileProxy: done" % self
.getName()) 
2220     def _proxyFromChildToParent(self
): 
2222         # Read output from the child process, and (for now) just write 
2227                 log
.info("[%s] _OutFileProxy: waiting for read on child (%r)"\
 
2228                          % (self
.getName(), self
.fChild
)) 
2229                 text 
= self
.fChild
.read(CHUNKSIZE
) 
2231                 # Ignore: IOError: [Errno 9] Bad file descriptor 
2232                 # XXX Do we *know* we want to do that? 
2233                 log
.info("[%s] _OutFileProxy: error reading from child (%r), "\
 
2234                          "shutting down: %s", self
.getName(), self
.fChild
, ex
) 
2237                 # Empty text signifies that the pipe has been closed on 
2239                 log
.info("[%s] _OutFileProxy: observed close of child (%r)"\
 
2240                          % (self
.getName(), self
.fChild
)) 
2243             log
.info("[%s] _OutFileProxy: text(len=%d): %r", 
2244                      self
.getName(), len(text
), text
) 
2245             self
.fParent
.write(text
) 
2249 if sys
.platform
.startswith("linux"): 
2251         """Mixin class for various classes in the Process hierarchy to 
2252         work around the known LinuxThreads bug where one cannot .wait() 
2253         on a created process from a subthread of the thread that created 
2257             class ProcessXXX(_ThreadFixer, BrokenProcessXXX): 
2258                 _pclass = BrokenProcessXXX 
2261             Because we must do all real os.wait() calls on the child 
2262             process from the thread that spawned it, we use a proxy 
2263             thread whose only responsibility is just that. The proxy 
2264             thread just starts the child and then immediately wait's for 
2265             the child to terminate. On termination is stores the exit 
2266             status (for use by the main thread) and notifies any thread 
2267             waiting for this termination (possibly the main thread). The 
2268             overriden .wait() uses this stored exit status and the 
2269             termination notification to simulate the .wait(). 
2271         def __init__(self
, *args
, **kwargs
): 
2272             # Keep a reference to 'log' ensure it is around for this object's 
2275             self
.__waiter 
= None 
2276             self
.__hasTerminated 
= threading
.Condition() 
2277             self
.__terminationResult 
= None 
2278             self
.__childStarted 
= threading
.Condition() 
2279             self
._pclass
.__init
__(self
, *args
, **kwargs
) 
2281         def _forkAndExecChildOnUnix(self
, *args
, **kwargs
): 
2282             """Fork and start the child process do it in a special subthread 
2283             that will negotiate subsequent .wait()'s. 
2285             Sets self._pid as a side effect. 
2287             self
.__waiter 
= threading
.Thread( 
2288                 target
=self
.__launchAndWait
, args
=args
, kwargs
=kwargs
) 
2290             # Start subthread that will launch child and wait until it 
2292             self
.__childStarted
.acquire() 
2293             self
.__waiter
.start() 
2294             self
.__childStarted
.wait() 
2295             self
.__childStarted
.release() 
2297         def __launchAndWait(self
, *args
, **kwargs
): 
2298             """Launch the given command and wait for it to terminate. 
2300             When the process has terminated then store its exit value 
2303             logfix
.info("start child in thread %s", 
2304                         threading
.currentThread().getName()) 
2306             # Spawn the child process and notify the main thread of 
2308             self
.__childStarted
.acquire() 
2309             self
._pclass
._forkAndExecChildOnUnix
(self
, *args
, **kwargs
) 
2310             self
.__childStarted
.notifyAll() 
2311             self
.__childStarted
.release() 
2313             # Wait on the thread and store appropriate results when 
2316                 waitResult 
= self
._pclass
.wait(self
) 
2317             except ProcessError
, ex
: 
2319             self
.__hasTerminated
.acquire() 
2320             self
.__terminationResult 
= waitResult
 
2321             self
.__hasTerminated
.notifyAll() 
2322             self
.__hasTerminated
.release() 
2324             self
.__waiter 
= None # drop ref that would keep instance alive 
2326         def wait(self
, timeout
=None):  
2327             # If the process __hasTerminated then return the exit 
2328             # status. Otherwise simulate the wait as appropriate. 
2330             #   - This class is only used on linux so 'timeout' has the 
2331             #     Unix 'timeout' semantics. 
2332             self
.__hasTerminated
.acquire() 
2333             if self
.__terminationResult 
is None: 
2334                 if timeout 
== os
.WNOHANG
:   # Poll. 
2335                     self
.__hasTerminated
.wait(0) 
2336                 else:                       # Block until process finishes. 
2337                     self
.__hasTerminated
.wait() 
2338             terminationResult 
= self
.__terminationResult
 
2339             self
.__hasTerminated
.release() 
2341             if terminationResult 
is None: 
2342                 # process has not finished yet 
2343                 raise ProcessError("Wait for process timed out.", 
2345             elif isinstance(terminationResult
, Exception): 
2346                 # some error waiting for process termination 
2347                 raise terminationResult
 
2349                 # the process terminated 
2350                 return terminationResult
 
2352     _ThreadBrokenProcess 
= Process
 
2353     class Process(_ThreadFixer
, _ThreadBrokenProcess
): 
2354         _pclass 
= _ThreadBrokenProcess
 
2356     _ThreadBrokenProcessOpen 
= ProcessOpen
 
2357     class ProcessOpen(_ThreadFixer
, _ThreadBrokenProcessOpen
): 
2358         _pclass 
= _ThreadBrokenProcessOpen
 
2360     _ThreadBrokenProcessProxy 
= ProcessProxy
 
2361     class ProcessProxy(_ThreadFixer
, _ThreadBrokenProcessProxy
): 
2362         _pclass 
= _ThreadBrokenProcessProxy