diff options
| author | Arturo FilastoĢ <hellais@torproject.org> | 2011-08-23 01:33:13 +0200 | 
|---|---|---|
| committer | Arturo FilastoĢ <hellais@torproject.org> | 2011-08-23 01:33:13 +0200 | 
| commit | 2e645039c2ea7a7e0684e46799db2a901a5d3cae (patch) | |
| tree | a7e064df1a857f1cf9c94d333ba42862eeffa39f /packages/torouter-web/src | |
| parent | fb4546cfd1ab55341508271faeb556bab9c39f14 (diff) | |
| download | torouter-2e645039c2ea7a7e0684e46799db2a901a5d3cae.tar.gz torouter-2e645039c2ea7a7e0684e46799db2a901a5d3cae.zip  | |
Fix #3790 Add a daemon class and make tor web ui run as such.
Diffstat (limited to 'packages/torouter-web/src')
| -rw-r--r-- | packages/torouter-web/src/daemon.py | 129 | ||||
| -rw-r--r-- | packages/torouter-web/src/runui.py | 63 | 
2 files changed, 173 insertions, 19 deletions
diff --git a/packages/torouter-web/src/daemon.py b/packages/torouter-web/src/daemon.py new file mode 100644 index 0000000..4ccc15c --- /dev/null +++ b/packages/torouter-web/src/daemon.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python + +import sys, os, time, atexit +from signal import SIGTERM  + +class Daemon: +	""" +	A generic daemon class. +	 +	Usage: subclass the Daemon class and override the run() method +	""" +	def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): +		self.stdin = stdin +		self.stdout = stdout +		self.stderr = stderr +		self.pidfile = pidfile +	 +	def daemonize(self): +		""" +		do the UNIX double-fork magic, see Stevens' "Advanced  +		Programming in the UNIX Environment" for details (ISBN 0201563177) +		http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16 +		""" +		try:  +			pid = os.fork()  +			if pid > 0: +				# exit first parent +				sys.exit(0)  +		except OSError, e:  +			sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) +			sys.exit(1) +	 +		# decouple from parent environment +		#os.chdir("/")  +		os.setsid()  +		os.umask(0)  +	 +		# do second fork +		try:  +			pid = os.fork()  +			if pid > 0: +				# exit from second parent +				sys.exit(0)  +		except OSError, e:  +			sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) +			sys.exit(1)  +	 +		# redirect standard file descriptors +		sys.stdout.flush() +		sys.stderr.flush() +		si = file(self.stdin, 'r') +		so = file(self.stdout, 'a+') +		se = file(self.stderr, 'a+', 0) +		os.dup2(si.fileno(), sys.stdin.fileno()) +		os.dup2(so.fileno(), sys.stdout.fileno()) +		os.dup2(se.fileno(), sys.stderr.fileno()) +	 +		# write pidfile +		atexit.register(self.delpid) +		pid = str(os.getpid()) +		file(self.pidfile,'w+').write("%s\n" % pid) +	 +	def delpid(self): +		os.remove(self.pidfile) + +	def start(self): +		""" +		Start the daemon +		""" +		# Check for a pidfile to see if the daemon already runs +		try: +			pf = file(self.pidfile,'r') +			pid = int(pf.read().strip()) +			pf.close() +		except IOError: +			pid = None +	 +		if pid: +			message = "pidfile %s already exist. Daemon already running?\n" +			sys.stderr.write(message % self.pidfile) +			sys.exit(1) +		 +		# Start the daemon +		self.daemonize() +		self.run() + +	def stop(self): +		""" +		Stop the daemon +		""" +		# Get the pid from the pidfile +		try: +			pf = file(self.pidfile,'r') +			pid = int(pf.read().strip()) +			pf.close() +		except IOError: +			pid = None +	 +		if not pid: +			message = "pidfile %s does not exist. Daemon not running?\n" +			sys.stderr.write(message % self.pidfile) +			return # not an error in a restart + +		# Try killing the daemon process	 +		try: +			while 1: +				os.kill(pid, SIGTERM) +				time.sleep(0.1) +		except OSError, err: +			err = str(err) +			if err.find("No such process") > 0: +				if os.path.exists(self.pidfile): +					os.remove(self.pidfile) +			else: +				print str(err) +				sys.exit(1) + +	def restart(self): +		""" +		Restart the daemon +		""" +		self.stop() +		self.start() + +	def run(self): +		""" +		You should override this method when you subclass Daemon. It will be called after the process has been +		daemonized by start() or restart(). +		""" diff --git a/packages/torouter-web/src/runui.py b/packages/torouter-web/src/runui.py index d5c7c9e..488c483 100644 --- a/packages/torouter-web/src/runui.py +++ b/packages/torouter-web/src/runui.py @@ -3,6 +3,8 @@  # by Arturo Filasto' <hellais@torproject.org>  # +import sys, time, os +from daemon import Daemon  import web  from tui import config  import tui.controllers @@ -10,27 +12,50 @@ import tui.controllers  from tui.utils import session  from tui.view import render -  # This is the main structure of URLs  urls = ( -    '/', 'tui.controllers.main.index', -#    '/config/(tor|router)', 'tui.controllers.main.config', -    '/network', 'tui.controllers.network.main', -    '/network/firewall', 'tui.controllers.network.firewall', -    '/network/wireless', 'tui.controllers.network.wireless', -    '/network/wired', 'tui.controllers.network.wired', -    '/network/status', 'tui.controllers.network.status', -    '/tor', 'tui.controllers.tor.status', -    '/tor/config', 'tui.controllers.tor.torrc', -    '/logout', 'tui.controllers.main.logout' -    ) -#    '/wizard/([0-9a-f]{1,2})?', 'tui.controllers.wizard.step', -#    '/status', 'tui.controllers.status') +   '/', 'tui.controllers.main.index', +# '/config/(tor|router)', 'tui.controllers.main.config', +   '/network', 'tui.controllers.network.main', +   '/network/firewall', 'tui.controllers.network.firewall', +   '/network/wireless', 'tui.controllers.network.wireless', +   '/network/wired', 'tui.controllers.network.wired', +   '/network/status', 'tui.controllers.network.status', +   '/tor', 'tui.controllers.tor.status', +   '/tor/config', 'tui.controllers.tor.torrc', +   '/logout', 'tui.controllers.main.logout' +   ) +# '/wizard/([0-9a-f]{1,2})?', 'tui.controllers.wizard.step', +# '/status', 'tui.controllers.status') + +app = web.application(urls, globals()) +# add session management to the app +session.add_session_to_app(app) +app.internalerror = web.debugerror +class TorWebDaemon(Daemon): +  def run(self): +    app.run() + +DEBUG = False  if __name__ == "__main__": -  app = web.application(urls, globals()) -  # Add session management to the app -  session.add_session_to_app(app) -  app.internalerror = web.debugerror -  app.run() +  if DEBUG: +    app.run() +  service = TorWebDaemon(os.path.join(os.getcwd(),'tui.pid')) +  if len(sys.argv) == 2: +    if 'start' == sys.argv[1]: +      sys.argv[1] = '8080' +      service.start() +    elif 'stop' == sys.argv[1]: +      service.stop() +    elif 'restart' == sys.argv[1]: +      service.restart() +    else: +      print "Unknown command" +      sys.exit(2) +    sys.exit(0) +  else: +    print "usage: %s start|stop|restart" % sys.argv[0] +    sys.exit(2) +  | 
