diff options
author | Alexander Sulfrian <alexander@sulfrian.net> | 2016-03-10 03:30:03 +0100 |
---|---|---|
committer | Alexander Sulfrian <alexander@sulfrian.net> | 2016-03-10 03:30:03 +0100 |
commit | 2a9bcee9e665da5af4f27b8d54b6d89f458805b1 (patch) | |
tree | 51898d99bceac0d3895f8720b02ba6e8fff242b3 | |
parent | 9ac127450231ac12772b36f9794d3336f2615e85 (diff) | |
parent | 5c897e15cef7edce935c3bd222dd3d5c0a6956f1 (diff) | |
download | spline-startup-2a9bcee9e665da5af4f27b8d54b6d89f458805b1.tar.gz spline-startup-2a9bcee9e665da5af4f27b8d54b6d89f458805b1.tar.bz2 spline-startup-2a9bcee9e665da5af4f27b8d54b6d89f458805b1.zip |
Merge commit '1.5' into debian
* commit '1.5':
Bump version
Non-Blocking read of subprocess output
Ignore SIGCHLD to cleanup child and remove defunct processes
Use correct variable
-rwxr-xr-x | spline-startup | 62 |
1 files changed, 54 insertions, 8 deletions
diff --git a/spline-startup b/spline-startup index 2c7dc54..fc1404f 100755 --- a/spline-startup +++ b/spline-startup @@ -2,15 +2,18 @@ from __future__ import print_function import argparse +import fcntl import os import pwd +import select +import signal import sys import syslog from subprocess import Popen, PIPE, STDOUT from pipes import quote -VERSION = '1.4' +VERSION = '1.5' def is_root(): @@ -40,6 +43,51 @@ def _get_users(config): return users +class Executor(Popen): + def __init__(self, *args, **kwargs): + self.running = True + + self.orig_signal = signal.signal(signal.SIGCHLD, self._signal) + return super(Executor, self).__init__(*args, **kwargs) + + def readlines(self): + fl = fcntl.fcntl(self.stdout, fcntl.F_GETFL) + fcntl.fcntl(self.stdout, fcntl.F_SETFL, fl | os.O_NONBLOCK) + + buffer = '' + while self.running: + try: + ready = select.select([self.stdout], [], [], 0) + except select.error: + pass + + if ready[0] != []: + buffer += self.stdout.read(8192) + lines = buffer.splitlines() + for line in lines[:-1]: + yield line + if len(lines) > 0: + buffer = lines[-1] + + self.wait() + + try: + buffer += self.stdout.read(8192) + except: + pass + + for line in buffer.splitlines(): + yield line + + def wait(self): + result = super(Executor, self).wait() + signal.signal(signal.SIGCHLD, self.orig_signal) + return result + + def _signal(self, *args): + self.running = False + + class SplineStartup(object): def __init__(self): @@ -103,12 +151,9 @@ class SplineStartup(object): def _call(self, cmd): self._pinfo('Calling: %s' % ' '.join(cmd)) if not self.options.dry_run: - proc = Popen(cmd, stdout=PIPE, stderr=STDOUT) - output, _ = proc.communicate() - output = output.strip() - if output != '': - for line in output.split('\n'): - self._pinfo(line) + proc = Executor(cmd, stdout=PIPE, stderr=STDOUT) + for line in proc.readlines(): + self._pinfo(line) return proc.returncode else: return 0 @@ -166,7 +211,7 @@ class SplineStartup(object): user = pwd.getpwnam(username) self._run_scripts(user, self.options.actions) except KeyError: - self._perror("Invalid user '%s'" % user) + self._perror("Invalid user '%s'" % username) else: userlist = _get_users(self.options.config) for user in userlist: @@ -174,6 +219,7 @@ class SplineStartup(object): def main(): + signal.signal(signal.SIGCHLD, signal.SIG_IGN) app = SplineStartup() app.run() |