~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to bzrplugins/lpserve/__init__.py

  • Committer: John Arbash Meinel
  • Date: 2010-09-03 20:19:44 UTC
  • mto: This revision was merged to the branch mainline in revision 11773.
  • Revision ID: jameinel@falco-lucid-20100903201944-ny27a75mynzdd3v0
Still not quite working right, but getting better.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
import resource
19
19
import shlex
20
20
import shutil
 
21
import signal
21
22
import socket
22
23
import sys
23
24
import tempfile
334
335
        # TODO: I think we can change this to a simple 'while True: (c_pid,
335
336
        # status) = os.wait() if c_pid == 0: break. But that needs some
336
337
        # testing.
337
 
        for child_pid, child_path in self._child_processes.iteritems():
338
 
            remove_child = True
339
 
            try:
340
 
                (c_pid, status) = os.waitpid(child_pid, os.WNOHANG)
341
 
            except OSError, e:
342
 
                trace.warning('Exception while checking child %s status: %s'
343
 
                              % (child_pid, e))
344
 
            else:
345
 
                if c_pid == 0: # Child did not exit
346
 
                    remove_child = False
347
 
                else:
348
 
                    self.log(None, 'child %s exited with status: %s'
349
 
                                    % (c_pid, status))
350
 
            if remove_child:
351
 
                # On error or child exiting, stop tracking the child
352
 
                to_remove.append(child_pid)
353
 
        for c_id in to_remove:
354
 
            # Should we do something about the temporary paths?
 
338
        while self._child_processes:
 
339
            c_id, exit_code, rusage = os.wait3(os.WNOHANG)
 
340
            if c_id == 0:
 
341
                # No children stopped right now
 
342
                return
355
343
            c_path = self._child_processes.pop(c_id)
 
344
            trace.mutter('%s exited %s and usage: %s'
 
345
                         % (c_id, exit_code, rusage))
356
346
            if os.path.exists(c_path):
357
347
                # The child failed to cleanup after itself, do the work here
358
348
                trace.warning('Had to clean up after child %d: %s\n'
359
349
                              % (c_id, c_path))
360
350
                shutil.rmtree(c_path)
361
351
 
362
 
    def _wait_for_children(self):
 
352
    def _wait_secs_for_children(self, secs):
363
353
        start = time.time()
364
 
        end = start + self.WAIT_FOR_CHILDREN_TIMEOUT
 
354
        end = start + secs
365
355
        while self._child_processes:
366
356
            self._poll_children()
367
 
            if self.WAIT_FOR_CHILDREN_TIMEOUT > 0 and time.time() > end:
 
357
            if secs > 0 and time.time() > end:
368
358
                break
369
359
            time.sleep(self.SLEEP_FOR_CHILDREN_TIMEOUT)
 
360
 
 
361
    def _wait_for_children(self):
 
362
        self._wait_secs_for_children(self.WAIT_FOR_CHILDREN_TIMEOUT)
370
363
        if self._child_processes:
371
364
            trace.warning('Failed to stop children: %s'
372
365
                % ', '.join(map(str, self._child_processes)))
373
366
            for c_id, c_path in self._child_processes.iteritems():
 
367
                trace.warning('sending SIGINT to %d' % (c_id,))
 
368
                os.kill(c_id, signal.SIGINT)
 
369
            # We sent the SIGINT signal, see if they exited
 
370
            self._wait_secs_for_children(1.0)
 
371
        if self._child_processes:
 
372
            # No? Then maybe something more powerful
 
373
            for c_id, c_path in self._child_processes.iteritems():
 
374
                trace.warning('sending SIGKILL to %d' % (c_id,))
 
375
                os.kill(c_id, signal.SIGKILL)
 
376
            # We sent the SIGKILL signal, see if they exited
 
377
            self._wait_secs_for_children(1.0)
 
378
        if self._child_processes:
 
379
            for c_id, c_path in self._child_processes.iteritems():
374
380
                if os.path.exists(c_path):
375
 
                    trace.warning('Had to clean up after child %d: %s\n'
 
381
                    trace.warning('Cleaning up after immortal child %d: %s\n'
376
382
                                  % (c_id, c_path))
377
383
                    shutil.rmtree(c_path)
378
384
 
484
490
                sys.stdout.flush()
485
491
            elif channel == 2:
486
492
                sys.stderr.write(contents)
487
 
                sys.stdout.flush()
 
493
                sys.stderr.flush()
488
494
            else:
489
495
                raise RuntimeError('Invalid channel request.')
 
496
        return 0
490
497
 
491
498
register_command(cmd_launchpad_replay)
492
499