diff options
author | Aleksey Lim <alsroot@sugarlabs.org> | 2012-10-22 09:52:28 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@sugarlabs.org> | 2012-10-22 10:26:41 (GMT) |
commit | 7a327b5e48f2fbf01473015e705a0ceac2152b46 (patch) | |
tree | b0602fe5be0196b8374a3b02c054c3346a366079 | |
parent | c4635e62236dcd6087df448505f73c4fa8f1aa82 (diff) |
Update codelets
-rw-r--r-- | active_toolkit/application.py | 60 | ||||
-rw-r--r-- | active_toolkit/printf.py | 23 |
2 files changed, 59 insertions, 24 deletions
diff --git a/active_toolkit/application.py b/active_toolkit/application.py index 36f755a..1694301 100644 --- a/active_toolkit/application.py +++ b/active_toolkit/application.py @@ -17,12 +17,13 @@ $Repo: git://git.sugarlabs.org/alsroot/codelets.git$ $File: src/application.py$ -$Date: 2012-10-01$ +$Date: 2012-10-22$ """ import os import sys +import time import signal import logging import textwrap @@ -45,6 +46,11 @@ foreground = Option( default=False, type_cast=Option.bool_cast, short_option='-F', action='store_true', name='foreground') +replace = Option( + 'if application is already launched, replace it by new instance', + default=False, type_cast=Option.bool_cast, + action='store_true', name='replace') + no_hints = Option( _('suppress suggesting hints'), default=False, short_option='-H', action='store_true', @@ -247,9 +253,12 @@ class Application(object): if not exists(log_dir): os.makedirs(log_dir) enforce(os.access(log_dir, os.W_OK), 'No write access to %s', log_dir) + + # printf should still output to original streams + printf.stdout = os.fdopen(os.dup(sys.stdout.fileno()), 'w') + printf.stderr = os.fdopen(os.dup(sys.stderr.fileno()), 'w') + log_path = join(log_dir, '%s.log' % self.name) - sys.stdout.flush() - sys.stderr.flush() logfile = file(log_path, 'a+') os.dup2(logfile.fileno(), sys.stdout.fileno()) os.dup2(logfile.fileno(), sys.stderr.fileno()) @@ -258,6 +267,8 @@ class Application(object): class Daemon(Application): + _accept_pipe = None + def run(self): raise NotImplementedError() @@ -265,20 +276,31 @@ class Daemon(Application): pass @command('start in daemon mode', name='start', keep_stdout=True) - def _cmd_start(self): - pid = self.check_for_instance() - if pid: - printf.info('%s is already run with pid %s', self.name, pid) - return 1 + def cmd_start(self): + while True: + pid = self.check_for_instance() + if not pid: + break + if not replace.value: + printf.info('%s is already run with pid %s', self.name, pid) + return 1 + try: + printf.info('Kill previous %r instance', pid) + os.kill(pid, signal.SIGTERM) + except Exception: + pass + time.sleep(.5) + if foreground.value: self._launch() else: self.ensure_pidfile_path() self._daemonize() + return 0 @command('stop daemon', name='stop') - def _cmd_stop(self): + def cmd_stop(self): pid = self.check_for_instance() if pid: os.kill(pid, signal.SIGTERM) @@ -288,7 +310,7 @@ class Daemon(Application): return 1 @command('check for launched daemon', name='status') - def _cmd_status(self): + def cmd_status(self): pid = self.check_for_instance() if pid: printf.info('%s started', self.name) @@ -298,7 +320,7 @@ class Daemon(Application): return 1 @command('reopen log files in daemon mode', name='reload') - def _cmd_reload(self): + def cmd_reload(self): pid = self.check_for_instance() if not pid: printf.info('%s is not run', self.name) @@ -306,6 +328,11 @@ class Daemon(Application): os.kill(pid, signal.SIGHUP) logging.info('Reload %s process', self.name) + def accept(self): + if self._accept_pipe is not None: + os.close(self._accept_pipe) + self._accept_pipe = None + def _launch(self): logging.info('Start %s', self.name) @@ -321,16 +348,24 @@ class Daemon(Application): signal.signal(signal.SIGTERM, sigterm_cb) signal.signal(signal.SIGHUP, sighup_cb) + pid_path = self.new_instance() try: self.run() finally: self.epilog() + os.unlink(pid_path) def _daemonize(self): + accept_pipe = os.pipe() if os.fork() > 0: + os.close(accept_pipe[1]) + os.read(accept_pipe[0], 1) # Exit parent of the first child return + os.close(accept_pipe[0]) + self._accept_pipe = accept_pipe[1] + # Decouple from parent environment os.chdir(os.sep) os.setsid() @@ -345,7 +380,6 @@ class Daemon(Application): stdin = file('/dev/null') os.dup2(stdin.fileno(), sys.stdin.fileno()) - pid_path = self.new_instance() try: self._launch() except Exception: @@ -354,8 +388,6 @@ class Daemon(Application): else: logging.info('Stopped %s', self.name) status = 0 - finally: - os.unlink(pid_path) exit(status) diff --git a/active_toolkit/printf.py b/active_toolkit/printf.py index 8cc9a37..c292b7e 100644 --- a/active_toolkit/printf.py +++ b/active_toolkit/printf.py @@ -17,7 +17,7 @@ $Repo: git://git.sugarlabs.org/alsroot/codelets.git$ $File: src/printf.py$ -$Date: 2012-08-16$ +$Date: 2012-10-22$ """ @@ -35,6 +35,9 @@ BOLD = '\033[1m' BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = \ ['\033[1;%dm' % (30 + i_) for i_ in range(8)] +stdout = sys.stdout +stderr = sys.stderr + _hints = [] _last_line_len = 0 _last_progress = [] @@ -50,7 +53,7 @@ def dump(message, *args): `%` arguments to expand `message` value """ - _dump(False, sys.stdout, '', [message, args], '\n') + _dump(False, stdout, '', [message, args], '\n') def info(message, *args): @@ -62,7 +65,7 @@ def info(message, *args): `%` arguments to expand `message` value """ - _dump(True, sys.stderr, None, [message, args], '\n') + _dump(True, stderr, None, [message, args], '\n') _dump_progress() @@ -103,7 +106,7 @@ def exception(message=None, *args): message += ': %s' % error else: message = str(error) - _dump(True, sys.stderr, None, message, '\n') + _dump(True, stderr, None, message, '\n') if logging.getLogger().level > logging.INFO: hint('Use -D argument for debug info, ' @@ -112,7 +115,7 @@ def exception(message=None, *args): hint('Use -DD argument for full debuging output and tracebacks') else: for i in tb_list: - _dump(True, sys.stderr, ' ', i, '\n') + _dump(True, stderr, ' ', i, '\n') _dump_progress() @@ -128,7 +131,7 @@ def scan_yn(message, *args): `True` if user's input was `Y` """ - _dump(True, sys.stderr, None, [message, args], ' [Y/N] ') + _dump(True, stderr, None, [message, args], ' [Y/N] ') answer = raw_input() _dump_progress() return answer and answer in 'Yy' @@ -153,7 +156,7 @@ def progress(message, *args): def clear_progress(): """Clear status line on program exit.""" if _last_line_len: - sys.stderr.write(chr(13) + ' ' * _last_line_len + chr(13)) + stderr.write(chr(13) + ' ' * _last_line_len + chr(13)) def hint(message, *args): @@ -179,7 +182,7 @@ def flush_hints(): if _hints: dump('') while _hints: - _dump(True, sys.stderr, '-- Hint: ', _hints.pop(0), '\n') + _dump(True, stderr, '-- Hint: ', _hints.pop(0), '\n') def _dump(is_status, stream, prefix, *args): @@ -222,5 +225,5 @@ def _dump(is_status, stream, prefix, *args): def _dump_progress(): - _dump(True, sys.stderr, ' ', _last_progress, chr(13)) - sys.stderr.flush() + _dump(True, stderr, ' ', _last_progress, chr(13)) + stderr.flush() |