Created
August 6, 2009 14:53
-
-
Save riffm/163356 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
import sys | |
import logging | |
import os | |
from os import path | |
logger = logging.getLogger(__name__) | |
def prepare_dir(filename): | |
dir = path.dirname(filename) | |
if not path.isdir(dir): | |
os.makedirs(dir) | |
def doublefork(pidfile, logfile, cur_dir): | |
try: | |
if os.fork() > 0: | |
sys.exit(0) | |
except OSError, e: | |
sys.exit('fork #1 failed: (%d) %s\n' % (e.errno, e.strerror)) | |
os.setsid() | |
os.chdir(cur_dir) | |
os.umask(002) | |
# The second fork _is_ necessary. The first fork accomplishes | |
# two things - allow the shell to return, and allow you to do a setsid(). | |
# The setsid() removes yourself from your controlling terminal. | |
# You see, before, you were still listed as a job of your previous process, | |
# and therefore the user might accidentally send you a signal. | |
# setsid() gives you a new session, and removes the existing controlling terminal. | |
# The problem is, you are now a session leader. | |
# As a session leader, if you open a file descriptor that is a terminal, | |
# it will become your controlling terminal (oops!). | |
# Therefore, the second fork makes you NOT be a session leader. | |
# Only session leaders can acquire a controlling terminal, | |
# so you can open up any file you wish without worrying | |
# that it will make you a controlling terminal. | |
# So - first fork - allow shell to return, and permit you to call setsid() | |
# Second fork - prevent you from accidentally reacquiring a controlling terminal. | |
try: | |
if os.fork() > 0: | |
sys.exit(0) | |
except OSError, e: | |
sys.exit('fork #2 failed: (%d) %s\n' % (e.errno, e.strerror)) | |
si = open('/dev/null', 'r') | |
so = open(logfile, 'a+', 0) | |
# Even safer to flush first. | |
# Before dup'ing a new file into the underlying stdout/stderr file descriptors, | |
# you should flush the stdio buffers. | |
# Otherwise, it is entirely possible that pending output could get sent to the wrong file. | |
sys.stdout.flush() | |
sys.stderr.flush() | |
os.dup2(si.fileno(), sys.stdin.fileno()) | |
os.dup2(so.fileno(), sys.stdout.fileno()) | |
os.dup2(so.fileno(), sys.stderr.fileno()) | |
sys.stdout = sys.stderr = so | |
fp = open(pidfile, 'w') | |
fp.write(str(os.getpid())) | |
fp.close() | |
def fastcgi(wsgi_app, cur_dir, bind='', pidfile='', logfile='', daemon=False): | |
"""Run fastcgi server at ./run/fcgi.sock""" | |
from flup.server import fcgi | |
run_dir = path.join(cur_dir, 'run') | |
pidfile = pidfile or path.join(run_dir, 'flup.pid') | |
prepare_dir(pidfile) | |
logfile = logfile or path.join(run_dir, 'flup.log') | |
prepare_dir(logfile) | |
if ':' in bind: | |
host, port = bind.split(':') | |
port = int(port) | |
else: | |
bind = bind or path.join(run_dir, 'fcgi.sock') | |
prepare_dir(bind) | |
if daemon: | |
if path.isfile(pidfile): | |
fp = open(pidfile, 'r') | |
pid = int(fp.read()) | |
fp.close() | |
try: | |
os.kill(pid, 0) | |
print 'process allready running' | |
sys.exit(1) | |
except OSError, err: | |
logger.info('Process allready running: (%d) %s\n' % \ | |
(err.errno, err.strerror)) | |
doublefork(pidfile, logfile, cur_dir) | |
logger.info("Starting FastCGI server (flup), current dir '%s'" % cur_dir) | |
fcgi.WSGIServer(wsgi_app, bindAddress=bind, umask=002, debug=False).run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment