Ejemplo n.º 1
0
class DaemonProcess(GObject.GObject):
    __gsignals__ = {
        # line(text)	- emited when process outputs full line
        b"line": (GObject.SIGNAL_RUN_FIRST, None, (object, )),
        # exit(code)	- emited when process exits
        b"exit": (GObject.SIGNAL_RUN_FIRST, None, (int, )),
        # failed(exception) - emited if process fails to start
        b"failed": (GObject.SIGNAL_RUN_FIRST, None, (object, )),
    }
    SCROLLBACK_SIZE = 500  # Maximum number of output lines stored in memory

    def __init__(self, commandline):
        """ commandline should be list of arguments """
        GObject.GObject.__init__(self)
        self.commandline = commandline
        self._proc = None

    def start(self):
        os.environ["STNORESTART"] = "1"  # see syncthing --help
        os.environ["STNOUPGRADE"] = "1"  # hopefully implemented later
        try:
            self._cancel = Gio.Cancellable()
            if IS_WINDOWS:
                # Windows
                sinfo = STARTUPINFO()
                sinfo.dwFlags = STARTF_USESHOWWINDOW
                sinfo.wShowWindow = 0
                self._proc = Popen(self.commandline,
                                   stdin=PIPE,
                                   stdout=PIPE,
                                   stderr=PIPE,
                                   startupinfo=sinfo)
                self._stdout = WinPopenReader(self._proc)
                self._check = GLib.timeout_add_seconds(1, self._cb_check_alive)
            elif HAS_SUBPROCESS:
                # New Gio
                flags = Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_MERGE
                self._proc = Gio.Subprocess.new(self.commandline, flags)
                self._proc.wait_check_async(None, self._cb_finished)
                self._stdout = self._proc.get_stdout_pipe()
            else:
                # Gio < 3.12 - Gio.Subprocess is missing :(
                self._proc = Popen(self.commandline, stdout=PIPE)
                self._stdout = Gio.UnixInputStream.new(
                    self._proc.stdout.fileno(), False)
                self._check = GLib.timeout_add_seconds(1, self._cb_check_alive)
        except Exception, e:
            # Startup failed
            self.emit("failed", e)
            return
        self._lines = deque([], DaemonProcess.SCROLLBACK_SIZE)
        self._buffer = ""
        self._stdout.read_bytes_async(256, 0, self._cancel, self._cb_read, ())
Ejemplo n.º 2
0
class DaemonProcess(GObject.GObject):
	__gsignals__ = {
		# line(text)	- emited when process outputs full line
		b"line"			: (GObject.SIGNAL_RUN_FIRST, None, (object,)),
		# exit(code)	- emited when process exits
		b"exit"			: (GObject.SIGNAL_RUN_FIRST, None, (int,)),
		# failed(exception) - emited if process fails to start
		b"failed"		: (GObject.SIGNAL_RUN_FIRST, None, (object,)),
	}
	SCROLLBACK_SIZE = 500	# Maximum number of output lines stored in memory
	
	def __init__(self, commandline):
		""" commandline should be list of arguments """
		GObject.GObject.__init__(self)
		self.commandline = commandline
		self._proc = None
	
	def start(self):
		os.environ["STNORESTART"] = "1"	# see syncthing --help
		os.environ["STNOUPGRADE"] = "1"	# hopefully implemented later
		try:
			self._cancel = Gio.Cancellable()
			if IS_WINDOWS:
				# Windows
				sinfo = STARTUPINFO()
				sinfo.dwFlags = STARTF_USESHOWWINDOW
				sinfo.wShowWindow = 0
				self._proc = Popen(self.commandline,
							stdin=PIPE, stdout=PIPE, stderr=PIPE,
							startupinfo=sinfo)
				self._stdout = WinPopenReader(self._proc)
				self._check = GLib.timeout_add_seconds(1, self._cb_check_alive)
			elif HAS_SUBPROCESS:
				# New Gio
				flags = Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_MERGE
				self._proc = Gio.Subprocess.new(self.commandline, flags)
				self._proc.wait_check_async(None, self._cb_finished)
				self._stdout = self._proc.get_stdout_pipe()
			else:
				# Gio < 3.12 - Gio.Subprocess is missing :(
				self._proc = Popen(self.commandline, stdout=PIPE)
				self._stdout = Gio.UnixInputStream.new(self._proc.stdout.fileno(), False)
				self._check = GLib.timeout_add_seconds(1, self._cb_check_alive)
		except Exception, e:
			# Startup failed
			self.emit("failed", e)
			return
		self._lines = deque([], DaemonProcess.SCROLLBACK_SIZE)
		self._buffer = ""
		self._stdout.read_bytes_async(256, 0, self._cancel, self._cb_read, ())
Ejemplo n.º 3
0
class DaemonProcess(GObject.GObject):
	__gsignals__ = {
		# line(text)	- emited when process outputs full line
		b"line"			: (GObject.SIGNAL_RUN_FIRST, None, (object,)),
		# exit(code)	- emited when process exits
		b"exit"			: (GObject.SIGNAL_RUN_FIRST, None, (int,)),
		# failed(exception) - emited if process fails to start
		b"failed"		: (GObject.SIGNAL_RUN_FIRST, None, (object,)),
	}
	SCROLLBACK_SIZE = 500	# Maximum number of output lines stored in memory
	PRIORITY_LOWEST		= 19
	PRIORITY_LOW		= 10
	PRIORITY_NORMAL		= 0
	PRIORITY_HIGH		= -10
	PRIORITY_HIGHEST	= -20
	
	def __init__(self, cmdline, priority=PRIORITY_NORMAL, max_cpus=0, env={}):
		""" cmdline should be list of arguments """
		GObject.GObject.__init__(self)
		self.cmdline = cmdline
		self.priority = priority
		self.env = { x:env[x] for x in env }
		self.env["STNORESTART"] = "1"	# see syncthing --help
		self.env["STNOUPGRADE"] = "1"
		if max_cpus > 0:
			self.env["GOMAXPROCS"] = str(max_cpus)
		self._proc = None
	
	def start(self):
		for x in self.env:
			os.environ[x] = self.env[x]
		try:
			self._cancel = Gio.Cancellable()
			if IS_WINDOWS:
				# Windows
				sinfo = STARTUPINFO()
				sinfo.dwFlags = STARTF_USESHOWWINDOW
				sinfo.wShowWindow = 0
				cflags = nice_to_priority_class(self.priority)
				self._proc = Popen(self.cmdline,
							stdin=PIPE, stdout=PIPE, stderr=PIPE,
							startupinfo=sinfo, creationflags=cflags)
				self._stdout = WinPopenReader(self._proc.stdout)
				self._check = GLib.timeout_add_seconds(1, self._cb_check_alive)
			elif HAS_SUBPROCESS:
				# New Gio
				flags = Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_MERGE
				if self.priority == 0:
					self._proc = Gio.Subprocess.new(self.cmdline, flags)
				else:
					# I just really do hope that there is no distro w/out nice command
					self._proc = Gio.Subprocess.new([ "nice", "-n", "%s" % self.priority ] + self.cmdline, flags)
				self._proc.wait_check_async(None, self._cb_finished)
				self._stdout = self._proc.get_stdout_pipe()
			else:
				# Gio < 3.12 - Gio.Subprocess is missing :(
				if self.priority == 0:
					self._proc = Popen(self.cmdline, stdout=PIPE)
				else:
					# still hoping
					self._proc = Popen([ "nice", "-n", "%s" % self.priority ], stdout=PIPE)
				self._stdout = Gio.UnixInputStream.new(self._proc.stdout.fileno(), False)
				self._check = GLib.timeout_add_seconds(1, self._cb_check_alive)
		except Exception, e:
			# Startup failed
			self.emit("failed", e)
			return
		self._lines = deque([], DaemonProcess.SCROLLBACK_SIZE)
		self._buffer = ""
		self._stdout.read_bytes_async(256, 0, self._cancel, self._cb_read, ())
Ejemplo n.º 4
0
class DaemonProcess(GObject.GObject):
    __gsignals__ = {
        # line(text)	- emitted when process outputs full line
        "line": (GObject.SIGNAL_RUN_FIRST, None, (object, )),
        # exit(code)	- emitted when process exits
        "exit": (GObject.SIGNAL_RUN_FIRST, None, (int, )),
        # failed(exception) - emitted if process fails to start
        "failed": (GObject.SIGNAL_RUN_FIRST, None, (object, )),
    }
    SCROLLBACK_SIZE = 500  # Maximum number of output lines stored in memory
    PRIORITY_LOWEST = 19
    PRIORITY_LOW = 10
    PRIORITY_NORMAL = 0
    PRIORITY_HIGH = -10
    PRIORITY_HIGHEST = -20

    def __init__(self, cmdline, priority=PRIORITY_NORMAL, max_cpus=0, env={}):
        """ cmdline should be list of arguments """
        GObject.GObject.__init__(self)
        self.cmdline = cmdline
        self.priority = priority
        self.env = {x: env[x] for x in env}
        self.env["STNORESTART"] = "1"  # see syncthing --help
        self.env["STNOUPGRADE"] = "1"
        if max_cpus > 0:
            self.env["GOMAXPROCS"] = str(max_cpus)
        self._proc = None

    def start(self):
        for x in self.env:
            os.environ[x] = self.env[x]
        try:
            self._cancel = Gio.Cancellable()
            if IS_WINDOWS:
                # Windows
                sinfo = STARTUPINFO()
                sinfo.dwFlags = STARTF_USESHOWWINDOW
                sinfo.wShowWindow = 0
                cflags = nice_to_priority_class(self.priority)
                self._proc = Popen(self.cmdline,
                                   stdin=PIPE,
                                   stdout=PIPE,
                                   stderr=PIPE,
                                   startupinfo=sinfo,
                                   creationflags=cflags)
                self._stdout = WinPopenReader(self._proc.stdout)
                self._check = GLib.timeout_add_seconds(1, self._cb_check_alive)
            elif HAS_SUBPROCESS:
                # New Gio
                flags = Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_MERGE
                if self.priority == 0:
                    self._proc = Gio.Subprocess.new(self.cmdline, flags)
                else:
                    # I just really do hope that there is no distro w/out nice command
                    self._proc = Gio.Subprocess.new(
                        ["nice", "-n", "%s" % self.priority] + self.cmdline,
                        flags)
                self._proc.wait_check_async(None, self._cb_finished)
                self._stdout = self._proc.get_stdout_pipe()
            else:
                # Gio < 3.12 - Gio.Subprocess is missing :(
                if self.priority == 0:
                    self._proc = Popen(self.cmdline, stdout=PIPE)
                else:
                    # still hoping
                    self._proc = Popen(
                        ["nice", "-n", "%s" % self.priority], stdout=PIPE)
                self._stdout = Gio.UnixInputStream.new(
                    self._proc.stdout.fileno(), False)
                self._check = GLib.timeout_add_seconds(1, self._cb_check_alive)
        except Exception as e:
            # Startup failed
            self.emit("failed", e)
            return
        self._lines = deque([], DaemonProcess.SCROLLBACK_SIZE)
        self._buffer = ""
        self._stdout.read_bytes_async(256, 0, self._cancel, self._cb_read, ())

    def _cb_read(self, pipe, results, *a):
        """ Handler for read_bytes_async """
        try:
            response = pipe.read_bytes_finish(results)
        except Exception as e:
            if not self._cancel.is_cancelled():
                log.exception(e)
                GLib.idle_add(pipe.read_bytes_async, 256, 1, None,
                              self._cb_read)
            return
        response = response.get_data().decode('utf-8')
        self._buffer = "%s%s" % (self._buffer, response)
        while "\n" in self._buffer:
            line, self._buffer = self._buffer.split("\n", 1)
            self._lines.append(line)
            self.emit('line', line)
        if not self._cancel.is_cancelled():
            GLib.idle_add(pipe.read_bytes_async, 256, 1, None, self._cb_read,
                          ())

    def _cb_check_alive(self, *a):
        """
		Repeatedly check if process is still alive.
		Called only on windows
		"""
        if self._proc == None:
            # Never started or killed really fast
            self.emit('exit', 1)
            self._cancel.cancel()
            if IS_WINDOWS: self._stdout.close()
            return False
        self._proc.poll()
        if self._proc.returncode is None:
            # Repeat until finished or canceled
            return (not self._cancel.is_cancelled())
        # Child just died :)
        self.emit('exit', self._proc.returncode)
        self._cancel.cancel()
        if IS_WINDOWS: self._stdout.close()
        return False

    def _cb_finished(self, proc, results):
        """
		Callback for wait_check_async.
		With Gio < 3.12, timer and _cb_check_alive is used.
		"""
        try:
            proc.wait_check_finish(results)
            log.info("Subprocess finished with code %s",
                     proc.get_exit_status())
        except GLib.GError:
            # Exited with exit code
            log.info("Subprocess exited with code %s", proc.get_exit_status())
        if proc.get_exit_status() == 127:
            # Command not found
            self.emit("failed", Exception("Command not found"))
        else:
            self.emit('exit', proc.get_exit_status())
        if IS_WINDOWS: self._stdout.close()
        self._cancel.cancel()

    def terminate(self):
        """ Terminates process (sends SIGTERM) """
        if not self._proc is None:
            if IS_WINDOWS:
                # Windows
                self._proc.terminate()
            elif HAS_SUBPROCESS:
                # Gio.Subprocess
                self._proc.send_signal(15)
            else:
                # subprocess.Popen
                self._proc.terminate()
            self._proc = None
            if IS_WINDOWS: self._stdout.close()
            self._cancel.cancel()

    def kill(self):
        """ Kills process (sends SIGTERM) """
        if not self._proc is None:
            if IS_WINDOWS:
                # Windows - can't actually kill
                self._proc.terminate()
            elif HAS_SUBPROCESS:
                # Gio.Subprocess
                self._proc.force_exit()
            else:
                # subprocess.Popen
                self._proc.kill()
            self._proc = None
            if IS_WINDOWS: self._stdout.close()
            self._cancel.cancel()

    def get_output(self):
        """ Returns process output as iterable list of lines """
        return self._lines

    def get_commandline(self):
        """ Returns commandline used to start process """
        return self.cmdline
Ejemplo n.º 5
0
class DaemonProcess(GObject.GObject):
    __gsignals__ = {
        # line(text)	- emited when process outputs full line
        b"line": (GObject.SIGNAL_RUN_FIRST, None, (object, )),
        # exit(code)	- emited when process exits
        b"exit": (GObject.SIGNAL_RUN_FIRST, None, (int, )),
        # failed(exception) - emited if process fails to start
        b"failed": (GObject.SIGNAL_RUN_FIRST, None, (object, )),
    }
    SCROLLBACK_SIZE = 500  # Maximum number of output lines stored in memory
    PRIORITY_LOWEST = 19
    PRIORITY_LOW = 10
    PRIORITY_NORMAL = 0
    PRIORITY_HIGH = -10
    PRIORITY_HIGHEST = -20

    def __init__(self, cmdline, priority=PRIORITY_NORMAL, max_cpus=0, env={}):
        """ cmdline should be list of arguments """
        GObject.GObject.__init__(self)
        self.cmdline = cmdline
        self.priority = priority
        self.env = {x: env[x] for x in env}
        self.env["STNORESTART"] = "1"  # see syncthing --help
        self.env["STNOUPGRADE"] = "1"
        if max_cpus > 0:
            self.env["GOMAXPROCS"] = str(max_cpus)
        self._proc = None

    def start(self):
        for x in self.env:
            os.environ[x] = self.env[x]
        try:
            self._cancel = Gio.Cancellable()
            if IS_WINDOWS:
                # Windows
                sinfo = STARTUPINFO()
                sinfo.dwFlags = STARTF_USESHOWWINDOW
                sinfo.wShowWindow = 0
                cflags = nice_to_priority_class(self.priority)
                self._proc = Popen(self.cmdline,
                                   stdin=PIPE,
                                   stdout=PIPE,
                                   stderr=PIPE,
                                   startupinfo=sinfo,
                                   creationflags=cflags)
                self._stdout = WinPopenReader(self._proc.stdout)
                self._check = GLib.timeout_add_seconds(1, self._cb_check_alive)
            elif HAS_SUBPROCESS:
                # New Gio
                flags = Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_MERGE
                if self.priority == 0:
                    self._proc = Gio.Subprocess.new(self.cmdline, flags)
                else:
                    # I just really do hope that there is no distro w/out nice command
                    self._proc = Gio.Subprocess.new(
                        ["nice", "-n", "%s" % self.priority] + self.cmdline,
                        flags)
                self._proc.wait_check_async(None, self._cb_finished)
                self._stdout = self._proc.get_stdout_pipe()
            else:
                # Gio < 3.12 - Gio.Subprocess is missing :(
                if self.priority == 0:
                    self._proc = Popen(self.cmdline, stdout=PIPE)
                else:
                    # still hoping
                    self._proc = Popen(
                        ["nice", "-n", "%s" % self.priority], stdout=PIPE)
                self._stdout = Gio.UnixInputStream.new(
                    self._proc.stdout.fileno(), False)
                self._check = GLib.timeout_add_seconds(1, self._cb_check_alive)
        except Exception, e:
            # Startup failed
            self.emit("failed", e)
            return
        self._lines = deque([], DaemonProcess.SCROLLBACK_SIZE)
        self._buffer = ""
        self._stdout.read_bytes_async(256, 0, self._cancel, self._cb_read, ())
Ejemplo n.º 6
0
class DaemonProcess(GObject.GObject):
	__gsignals__ = {
		# line(text)	- emitted when process outputs full line
		b"line"			: (GObject.SIGNAL_RUN_FIRST, None, (object,)),
		# exit(code)	- emitted when process exits
		b"exit"			: (GObject.SIGNAL_RUN_FIRST, None, (int,)),
		# failed(exception) - emitted if process fails to start
		b"failed"		: (GObject.SIGNAL_RUN_FIRST, None, (object,)),
	}
	SCROLLBACK_SIZE = 500	# Maximum number of output lines stored in memory
	PRIORITY_LOWEST		= 19
	PRIORITY_LOW		= 10
	PRIORITY_NORMAL		= 0
	PRIORITY_HIGH		= -10
	PRIORITY_HIGHEST	= -20
	
	def __init__(self, cmdline, priority=PRIORITY_NORMAL, max_cpus=0, env={}):
		""" cmdline should be list of arguments """
		GObject.GObject.__init__(self)
		self.cmdline = cmdline
		self.priority = priority
		self.env = { x:env[x] for x in env }
		self.env["STNORESTART"] = "1"	# see syncthing --help
		self.env["STNOUPGRADE"] = "1"
		if max_cpus > 0:
			self.env["GOMAXPROCS"] = str(max_cpus)
		self._proc = None
	
	def start(self):
		for x in self.env:
			os.environ[x] = self.env[x]
		try:
			self._cancel = Gio.Cancellable()
			if IS_WINDOWS:
				# Windows
				sinfo = STARTUPINFO()
				sinfo.dwFlags = STARTF_USESHOWWINDOW
				sinfo.wShowWindow = 0
				cflags = nice_to_priority_class(self.priority)
				self._proc = Popen(self.cmdline,
							stdin=PIPE, stdout=PIPE, stderr=PIPE,
							startupinfo=sinfo, creationflags=cflags)
				self._stdout = WinPopenReader(self._proc.stdout)
				self._check = GLib.timeout_add_seconds(1, self._cb_check_alive)
			elif HAS_SUBPROCESS:
				# New Gio
				flags = Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_MERGE
				if self.priority == 0:
					self._proc = Gio.Subprocess.new(self.cmdline, flags)
				else:
					# I just really do hope that there is no distro w/out nice command
					self._proc = Gio.Subprocess.new([ "nice", "-n", "%s" % self.priority ] + self.cmdline, flags)
				self._proc.wait_check_async(None, self._cb_finished)
				self._stdout = self._proc.get_stdout_pipe()
			else:
				# Gio < 3.12 - Gio.Subprocess is missing :(
				if self.priority == 0:
					self._proc = Popen(self.cmdline, stdout=PIPE)
				else:
					# still hoping
					self._proc = Popen([ "nice", "-n", "%s" % self.priority ], stdout=PIPE)
				self._stdout = Gio.UnixInputStream.new(self._proc.stdout.fileno(), False)
				self._check = GLib.timeout_add_seconds(1, self._cb_check_alive)
		except Exception as e:
			# Startup failed
			self.emit("failed", e)
			return
		self._lines = deque([], DaemonProcess.SCROLLBACK_SIZE)
		self._buffer = ""
		self._stdout.read_bytes_async(256, 0, self._cancel, self._cb_read, ())
	
	def _cb_read(self, pipe, results, *a):
		""" Handler for read_bytes_async """
		try:
			response = pipe.read_bytes_finish(results)
		except Exception as e:
			if not self._cancel.is_cancelled():
				log.exception(e)
				GLib.idle_add(pipe.read_bytes_async, 256, 1, None, self._cb_read)
			return
		response = response.get_data().decode('utf-8')
		self._buffer = "%s%s" % (self._buffer, response)
		while "\n" in self._buffer:
			line, self._buffer = self._buffer.split("\n", 1)
			self._lines.append(line)
			self.emit('line', line)
		if not self._cancel.is_cancelled():
			GLib.idle_add(pipe.read_bytes_async, 256, 1, None, self._cb_read, ())
	
	def _cb_check_alive(self, *a):
		"""
		Repeatedly check if process is still alive.
		Called only on windows
		"""
		if self._proc == None:
			# Never started or killed really fast
			self.emit('exit', 1)
			self._cancel.cancel()
			if IS_WINDOWS: self._stdout.close()
			return False
		self._proc.poll()
		if self._proc.returncode is None:
			# Repeat until finished or canceled
			return (not self._cancel.is_cancelled())
		# Child just died :)
		self.emit('exit', self._proc.returncode)
		self._cancel.cancel()
		if IS_WINDOWS: self._stdout.close()
		return False
	
	def _cb_finished(self, proc, results):
		"""
		Callback for wait_check_async.
		With Gio < 3.12, timer and _cb_check_alive is used.
		"""
		try:
			proc.wait_check_finish(results)
			log.info("Subprocess finished with code %s", proc.get_exit_status())
		except GLib.GError:
			# Exited with exit code
			log.info("Subprocess exited with code %s", proc.get_exit_status())
		if proc.get_exit_status() == 127:
			# Command not found
			self.emit("failed", Exception("Command not found"))
		else:
			self.emit('exit', proc.get_exit_status())
		if IS_WINDOWS: self._stdout.close()
		self._cancel.cancel()
	
	def terminate(self):
		""" Terminates process (sends SIGTERM) """
		if not self._proc is None:
			if IS_WINDOWS:
				# Windows
				self._proc.terminate()
			elif HAS_SUBPROCESS:
				# Gio.Subprocess
				self._proc.send_signal(15)
			else:
				# subprocess.Popen
				self._proc.terminate()
			self._proc = None
			if IS_WINDOWS: self._stdout.close()
			self._cancel.cancel()
	
	def kill(self):
		""" Kills process (sends SIGTERM) """
		if not self._proc is None:
			if IS_WINDOWS:
				# Windows - can't actually kill
				self._proc.terminate()
			elif HAS_SUBPROCESS:
				# Gio.Subprocess
				self._proc.force_exit()
			else:
				# subprocess.Popen
				self._proc.kill()
			self._proc = None
			if IS_WINDOWS: self._stdout.close()
			self._cancel.cancel()
	
	def get_output(self):
		""" Returns process output as iterable list of lines """
		return self._lines
	
	def get_commandline(self):
		""" Returns commandline used to start process """
		return self.cmdline