Skip to content
Permalink
Browse files

Support systemd socket activation

  • Loading branch information
timbertson committed May 15, 2012
1 parent 32c2877 commit 41a54723977d2042c5040ee15c0754e8a7cb5525
@@ -21,6 +21,7 @@ import subprocess
import tempfile, time
import os, sys, re
import stat
import socket
from optparse import OptionParser
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from SocketServer import ThreadingMixIn
@@ -35,6 +36,7 @@ os.environ['FROM_EDIT_SERVER'] = 'true'
processes = {}
INCREMENTAL = True
delay_in_minutes = 5
SYSTEMD_FIRST_SOCKET_FD = 3

class HttpError(RuntimeError):
pass
@@ -172,6 +174,15 @@ class Handler(BaseHTTPRequestHandler):
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
pass

class SocketInheritingHTTPServer(ThreadedHTTPServer):
"""A HttpServer subclass that takes over an inherited socket from systemd"""
def __init__(self, address_info, handler, fd, bind_and_activate=True):
ThreadedHTTPServer.__init__(self, address_info, handler, bind_and_activate=False)
self.socket = socket.fromfd(fd, self.address_family, self.socket_type)
if bind_and_activate:
# NOTE: systemd provides ready-bound sockets, so we only need to activate:
self.server_activate()

def main():
global delay_in_minutes, INCREMENTAL, open_cmd
try:
@@ -186,9 +197,15 @@ def main():
if args:
open_cmd = args

httpserv = ThreadedHTTPServer(('localhost', int(port)), Handler)
logging.info('edit-server PID is %s' % (os.getpid(),))
server_args = [('localhost', int(port)), Handler]
if os.environ.get('LISTEN_PID', None) == str(os.getpid()):
httpserv = SocketInheritingHTTPServer(*server_args, fd=SYSTEMD_FIRST_SOCKET_FD)
logging.info('edit-server started on socket fd %s' % (SYSTEMD_FIRST_SOCKET_FD,))
else:
httpserv = ThreadedHTTPServer(*server_args)
logging.info('edit-server started on port %s' % (port,))
httpserv.table = {}
logging.info('edit-server started on port %s' % (port,))
httpserv.serve_forever()
except KeyboardInterrupt:
httpserv.socket.close()
@@ -0,0 +1,23 @@
#!/usr/bin/python

# this script simulates what I believe systemd does when passing a socket over
# to a socket-activated service, which is useful in debugging issues.

import socket, os
HOST = 'localhost'
PORT = 9292
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
# Note that we don't call s.listen() as normal
fd = s.fileno()
os.dup2(fd, 3) # systemd starts passing fds at 3
pid = os.fork()
if pid == 0: # child
pid = os.getpid()
print "child pid = %s" % pid
os.environ['LISTEN_PID'] = str(pid)
os.execv(os.path.join(os.path.dirname(__file__), 'edit-server'), ['edit-server'])

ret = os.waitpid(pid, 0)
print "child returned %s" % (ret,)

This file was deleted.

@@ -4,7 +4,5 @@ Description=Edit Server
[Service]
ExecStart=/usr/bin/env 0launch -c http://gfxmonk.net/dist/0install/edit-server.xml
Restart=always

[Install]
WantedBy=default.target

StandardOutput=syslog
StandardError=syslog
@@ -0,0 +1,9 @@
[Unit]
Description=Edit Server

[Socket]
ListenStream=9292

[Install]
WantedBy=default.target

0 comments on commit 41a5472

Please sign in to comment.