diff --git a/resources/transport_solard/actions/run.yaml b/resources/transport_solard/actions/run.yaml index 541bf215..a6fe5bb4 100644 --- a/resources/transport_solard/actions/run.yaml +++ b/resources/transport_solard/actions/run.yaml @@ -2,6 +2,6 @@ sudo: yes tasks: - shell: pip install -e /vagrant/solard - - shell: start-stop-daemon --stop --make-pidfile --pidfile /tmp/solard.pid --chdir /vagrant/solard --startas /bin/bash -- -c "exec python /vagrant/solard/solard/tcp_server.py > /tmp/solard.log 2>&1" + - shell: start-stop-daemon --stop --make-pidfile --pidfile /tmp/solard.pid --chdir /vagrant/solard --startas /bin/bash -- -c "exec /usr/local/bin/solard run --port {{solard_port}} --base tcp > /tmp/solard.log 2>&1" ignore_errors: True - - shell: start-stop-daemon -b --start --make-pidfile --pidfile /tmp/solard.pid --chdir /vagrant/solard --startas /bin/bash -- -c "exec python /vagrant/solard/solard/tcp_server.py > /tmp/solard.log 2>&1" + - shell: start-stop-daemon -b --start --make-pidfile --pidfile /tmp/solard.pid --chdir /vagrant/solard --startas /bin/bash -- -c "exec /usr/local/bin/solard run --port {{solard_port}} --base tcp > /tmp/solard.log 2>&1" diff --git a/solard/setup.py b/solard/setup.py index 9cfe92e0..05377041 100644 --- a/solard/setup.py +++ b/solard/setup.py @@ -44,5 +44,8 @@ setup( packages=find_packages(), zip_safe=False, install_requires=find_requires(), - include_package_data=True + include_package_data=True, + entry_points={ + 'console_scripts': + ['solard = solard.server:cli']} ) diff --git a/solard/solard/server.py b/solard/solard/server.py new file mode 100644 index 00000000..9a8df6b5 --- /dev/null +++ b/solard/solard/server.py @@ -0,0 +1,26 @@ +import click + +@click.group() +def cli(): + pass + + +def validate_class(ctx, param, value): + supported = ('tcp', ) + if not value in supported: + raise click.BadParameter("%r is not one of %r" % (value, supported)) + return value + + +@cli.command() +@click.option('--base', default='tcp', callback=validate_class, type=str) +@click.option('--port', default=5555, type=int) +def run(base, port): + if base == 'tcp': + from solard.tcp_server import SolardTCPServer + runner = SolardTCPServer.run_solard + runner(port) + + +if __name__ == '__main__': + cli() diff --git a/solard/solard/tcp_server.py b/solard/solard/tcp_server.py index 7c2e07f2..993abc5c 100644 --- a/solard/solard/tcp_server.py +++ b/solard/solard/tcp_server.py @@ -20,7 +20,10 @@ from SocketServer import ThreadingTCPServer, BaseRequestHandler import socket +import threading +import errno import msgpack +import time import struct import errno import sys @@ -29,6 +32,7 @@ import pwd import os from types import GeneratorType + from solard.logger import logger from solard.core import SolardContext, SolardIface from solard.tcp_core import * @@ -251,7 +255,6 @@ class SolardTCPHandler(object): class SolardReqHandler(BaseRequestHandler): def handle(self): - close = True sock = self.request address = self.client_address h = SolardTCPHandler(sock, address) @@ -263,7 +266,7 @@ class SolardReqHandler(BaseRequestHandler): return if auth_state is None: # child forked - close = False + # we don't wait there, but in recycler return while True: if not h.process(): @@ -290,8 +293,28 @@ class SolardTCPServer(ThreadingTCPServer): # StreamServer.__init__(self, *args, **kwargs) ThreadingTCPServer.__init__(self, *args, **kwargs) + def dummy_recycle_childs(self): + # dummy child recycler, turns each 3 seconds + def child_recycler(): + while True: + try: + pid, status = os.waitpid(-1, 0) + logger.debug("Child %r ended with status=%d", pid, status) + except OSError as e: + if e.errno != errno.ECHILD: + raise + time.sleep(3) + th = threading.Thread(target=child_recycler) + th.daemon = True + th.start() + + @staticmethod + def run_solard(port): + s = SolardTCPServer(('0.0.0.0', port), SolardReqHandler) + s.dummy_recycle_childs() + return s.serve_forever() + if __name__ == '__main__': - s = SolardTCPServer(('0.0.0.0', 5555), SolardReqHandler) - s.serve_forever() + SolardTCPServer.run_solard(5555)