Changeset 27780

Show
Ignore:
Timestamp:
12/15/2009 10:17:02 AM (9 months ago)
Author:
exarkun
Message:

Merge forward, resolve numerous conflicts

Location:
branches/signal-process-group-2726-4/twisted
Files:
5 modified
2 copied

Legend:

Unmodified
Added
Removed
  • branches/signal-process-group-2726-4/twisted/internet/_dumbwin32proc.py

    r27356 r27780  
    1717import win32process 
    1818import win32security 
     19import win32job 
    1920 
    2021import pywintypes 
     
    3536from twisted.internet._baseprocess import BaseProcess 
    3637 
    37 def debug(msg): 
    38     import sys 
    39     print msg 
    40     sys.stdout.flush() 
     38 
    4139 
    4240class _Reaper(_pollingfile._PollableResource): 
     
    169167 
    170168        cmdline = quoteArguments(args) 
     169 
     170        self.job = win32job.CreateJobObject(None, None) 
    171171        # TODO: error detection here. 
    172172        def doCreate(): 
    173173            self.hProcess, self.hThread, self.pid, dwTid = win32process.CreateProcess( 
    174                 command, cmdline, None, None, 1, 0, env, path, StartupInfo) 
     174                command, cmdline, None, None, 1, win32con.CREATE_SUSPENDED, 
     175                env, path, StartupInfo) 
    175176        try: 
    176177            doCreate() 
     
    206207                        raise OSError(pwte2) 
    207208 
     209        win32job.AssignProcessToJobObject(self.job, self.hProcess) 
     210        win32process.ResumeThread(self.hThread) 
     211 
     212        win32file.CloseHandle(self.hThread) 
     213 
    208214        # close handles which only the child will use 
    209215        win32file.CloseHandle(hStderrW) 
     
    235241 
    236242 
     243    def _raiseUnknownSignal(self, signalID): 
     244        """ 
     245        Helper method raising an error when a given signal can't be handled. 
     246        """ 
     247        raise ValueError( 
     248            "Signal not handled: %s. " 
     249            "Only 'INT', 'TERM' or 'KILL' can be used." % (signalID,)) 
     250 
     251 
    237252    def signalProcess(self, signalID): 
     253        """ 
     254        Terminate process if C{signalID} is one of "INT", "TERM", or "KILL". 
     255 
     256        @type signalID: C{str} 
     257        """ 
    238258        if self.pid is None: 
    239259            raise error.ProcessExitedAlready() 
    240260        if signalID in ("INT", "TERM", "KILL"): 
    241261            win32process.TerminateProcess(self.hProcess, 1) 
     262        else: 
     263            self._raiseUnknownSignal(signalID) 
     264 
     265 
     266    def signalProcessGroup(self, signalID): 
     267        """ 
     268        Terminate process group if C{signalID} is one of "INT", "TERM", or 
     269        "KILL". 
     270 
     271        @type signalID: C{str} 
     272        """ 
     273        if self.pid is None: 
     274            raise error.ProcessExitedAlready() 
     275        if signalID in ("INT", "TERM", "KILL"): 
     276            win32job.TerminateJobObject(self.job, 1) 
     277        else: 
     278            self._raiseUnknownSignal(signalID) 
    242279 
    243280 
  • branches/signal-process-group-2726-4/twisted/internet/interfaces.py

    r27770 r27780  
    15061506        """ 
    15071507 
     1508 
    15081509    def signalProcess(signalID): 
    15091510        """ 
     
    15191520 
    15201521        @raise twisted.internet.error.ProcessExitedAlready: The process has 
    1521         already exited. 
    1522         """ 
     1522            already exited. 
     1523        """ 
     1524 
     1525 
     1526    def signalProcessGroup(signalID): 
     1527        """ 
     1528        Send a signal to every processes in the process group. C{signalID} 
     1529        takes the value as in L{signalProcess}. 
     1530        """ 
     1531 
    15231532 
    15241533 
  • branches/signal-process-group-2726-4/twisted/internet/process.py

    r26050 r27780  
    332332        if self.pid is None: 
    333333            raise ProcessExitedAlready() 
     334        os.kill(self.pid, signalID) 
     335 
     336 
     337    def signalProcessGroup(self, signalID): 
     338        """ 
     339        Send the given signal C{signalID} to the process group. It does the 
     340        same translation as L{signalProcess}. 
     341 
     342        @type signalID: C{str} or C{int} 
     343        """ 
     344        if signalID in ('HUP', 'STOP', 'INT', 'KILL', 'TERM'): 
     345            signalID = getattr(signal, 'SIG%s' % (signalID,)) 
     346        if self.pid is None: 
     347            raise ProcessExitedAlready() 
     348        self.pid = -self.pid 
    334349        os.kill(self.pid, signalID) 
    335350 
  • branches/signal-process-group-2726-4/twisted/test/mock_win32process.py

    r23212 r27780  
    1212import win32process 
    1313GetExitCodeProcess = win32process.GetExitCodeProcess 
     14ResumeThread = win32process.ResumeThread 
    1415STARTUPINFO = win32process.STARTUPINFO 
    1516 
  • branches/signal-process-group-2726-4/twisted/test/test_process.py

    r27135 r27780  
    266266    """ 
    267267 
    268     def __init__(self, deferred, sig): 
     268    def __init__(self, deferred, sig, method="signalProcess"): 
    269269        self.deferred = deferred 
    270270        self.signal = sig 
     271        self.method = method 
    271272 
    272273 
    273274    def outReceived(self, data): 
    274         self.transport.signalProcess(self.signal) 
     275        getattr(self.transport, self.method)(self.signal) 
    275276 
    276277 
     
    10991100 
    11001101 
     1102    def test_signalProcessGroup(self): 
     1103        """ 
     1104        Send a INT signal to a group of processes. 
     1105        """ 
     1106        exe = sys.executable 
     1107        scriptPath = util.sibpath(__file__, "process_signalgroup.py") 
     1108        d = defer.Deferred() 
     1109        p = SignalProtocol(d, "INT", "signalProcessGroup") 
     1110        reactor._handleSignals() 
     1111        proc = reactor.spawnProcess(p, exe, [exe, "-u", scriptPath, "parent"], 
     1112                                    env=None, 
     1113                                    usePTY=self.usePTY) 
     1114        pid = proc.pid 
     1115        def check(result): 
     1116            error = self.assertRaises(OSError, os.kill, -pid, 0) 
     1117            self.assertEquals(error[0], errno.ESRCH) 
     1118        return d.addCallback(check) 
     1119 
     1120 
    11011121    def test_errorInProcessEnded(self): 
    11021122        """ 
     
    19371957 
    19381958 
     1959 
     1960 
    19391961class PosixProcessTestCasePTY(unittest.TestCase, PosixProcessBase): 
    19401962    """ 
     
    20762098        """ 
    20772099        import win32api 
    2078  
    20792100        connected = defer.Deferred() 
    20802101        ended = defer.Deferred() 
     
    21192140 
    21202141        return defer.gatherResults([connected, ended]) 
     2142 
     2143 
     2144    def test_signalProcessGroup(self): 
     2145        """ 
     2146        Send a INT signal to a group of processes. 
     2147        """ 
     2148        exe = sys.executable 
     2149        scriptPath = util.sibpath(__file__, "process_signaljob.py") 
     2150        d = defer.Deferred() 
     2151        p = Win32SignalProtocol(d, "INT", "signalProcessGroup") 
     2152        reactor._handleSignals() 
     2153        proc = reactor.spawnProcess(p, exe, [exe, "-u", scriptPath, "parent"], 
     2154                                    env=None) 
     2155 
     2156        def check(result): 
     2157            # If we're here, both processes must have terminated, so it's just 
     2158            # a sanity check 
     2159            import win32job 
     2160            jobProcesses = win32job.QueryInformationJobObject(proc.job, 
     2161                win32job.JobObjectBasicProcessIdList) 
     2162            self.assertEquals(len(jobProcesses), 0) 
     2163        return d.addCallback(check) 
    21212164 
    21222165