Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@sugarlabs.org>2012-10-22 09:52:28 (GMT)
committer Aleksey Lim <alsroot@sugarlabs.org>2012-10-22 10:26:41 (GMT)
commit7a327b5e48f2fbf01473015e705a0ceac2152b46 (patch)
treeb0602fe5be0196b8374a3b02c054c3346a366079
parentc4635e62236dcd6087df448505f73c4fa8f1aa82 (diff)
Update codelets
-rw-r--r--active_toolkit/application.py60
-rw-r--r--active_toolkit/printf.py23
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()