Commit 361129da authored by Julien Muchembled's avatar Julien Muchembled

Always kill child processes gracefully

parent 0769f25f
import logging, errno, os, subprocess import logging, errno, os
from . import utils from . import utils
here = os.path.realpath(os.path.dirname(__file__)) here = os.path.realpath(os.path.dirname(__file__))
...@@ -21,7 +21,7 @@ def openvpn(iface, encrypt, *args, **kw): ...@@ -21,7 +21,7 @@ def openvpn(iface, encrypt, *args, **kw):
if not encrypt: if not encrypt:
args += '--cipher', 'none' args += '--cipher', 'none'
logging.debug('%r', args) logging.debug('%r', args)
return subprocess.Popen(args, **kw) return utils.Popen(args, **kw)
def server(iface, max_clients, dh_path, pipe_fd, port, proto, encrypt, *args, **kw): def server(iface, max_clients, dh_path, pipe_fd, port, proto, encrypt, *args, **kw):
...@@ -80,4 +80,4 @@ def router(subnet, hello_interval, table, log_path, state_path, pidfile, ...@@ -80,4 +80,4 @@ def router(subnet, hello_interval, table, log_path, state_path, pidfile,
if e.errno != errno.ENOENT: if e.errno != errno.ENOENT:
raise raise
logging.info('%r', cmd) logging.info('%r', cmd)
return subprocess.Popen(cmd, **kw) return utils.Popen(cmd, **kw)
import logging, random, socket, subprocess, threading, time import logging, random, socket, subprocess, time
from collections import deque from collections import deque
from itertools import chain from itertools import chain
from . import plib, utils from . import plib, utils
...@@ -126,21 +126,15 @@ class TunnelManager(object): ...@@ -126,21 +126,15 @@ class TunnelManager(object):
self._client_count + self._refresh_count)]: self._client_count + self._refresh_count)]:
self._kill(prefix) self._kill(prefix)
def _kill(self, prefix, kill=False): def _kill(self, prefix):
logging.info('Killing the connection with %u/%u...', logging.info('Killing the connection with %u/%u...',
int(prefix, 2), len(prefix)) int(prefix, 2), len(prefix))
connection = self._connection_dict.pop(prefix) connection = self._connection_dict.pop(prefix)
self.freeInterface(connection.iface) self.freeInterface(connection.iface)
p = connection.process
try: try:
getattr(p, 'kill' if kill else 'terminate')() connection.process.stop()
except OSError: except OSError:
pass # we already polled an exited process pass # we already polled an exited process
else:
t = threading.Timer(5, p.kill)
kill or t.start()
p.wait()
t.cancel()
logging.trace('Connection with %u/%u killed', logging.trace('Connection with %u/%u killed',
int(prefix, 2), len(prefix)) int(prefix, 2), len(prefix))
...@@ -280,7 +274,7 @@ class TunnelManager(object): ...@@ -280,7 +274,7 @@ class TunnelManager(object):
def killAll(self): def killAll(self):
for prefix in self._connection_dict.keys(): for prefix in self._connection_dict.keys():
self._kill(prefix, True) self._kill(prefix)
def handleTunnelEvent(self, msg): def handleTunnelEvent(self, msg):
try: try:
......
import argparse, errno, logging, os, shlex import argparse, errno, logging, os, shlex, signal, socket
import signal, struct, socket, textwrap, time import struct, subprocess, textwrap, threading, time
from OpenSSL import crypto from OpenSSL import crypto
logging_levels = logging.WARNING, logging.INFO, logging.DEBUG, 5 logging_levels = logging.WARNING, logging.INFO, logging.DEBUG, 5
...@@ -96,6 +96,17 @@ class ArgParser(argparse.ArgumentParser): ...@@ -96,6 +96,17 @@ class ArgParser(argparse.ArgumentParser):
ca /etc/re6stnet/ca.crt""", **kw) ca /etc/re6stnet/ca.crt""", **kw)
class Popen(subprocess.Popen):
def stop(self):
self.terminate()
t = threading.Timer(5, self.kill)
t.start()
r = self.wait()
t.cancel()
return r
def makedirs(path): def makedirs(path):
try: try:
os.makedirs(path) os.makedirs(path)
......
...@@ -214,13 +214,13 @@ def main(): ...@@ -214,13 +214,13 @@ def main():
if config.client: if config.client:
cleanup.append(plib.client('re6stnet', config.client, cleanup.append(plib.client('re6stnet', config.client,
config.encrypt, '--ping-restart', str(timeout), config.encrypt, '--ping-restart', str(timeout),
*config.openvpn_args).kill) *config.openvpn_args).stop)
elif server_tunnels: elif server_tunnels:
required('dh') required('dh')
for iface, (port, proto) in server_tunnels.iteritems(): for iface, (port, proto) in server_tunnels.iteritems():
cleanup.append(plib.server(iface, config.max_clients, cleanup.append(plib.server(iface, config.max_clients,
config.dh, write_pipe, port, proto, config.encrypt, config.dh, write_pipe, port, proto, config.encrypt,
'--ping-exit', str(timeout), *config.openvpn_args).kill) '--ping-exit', str(timeout), *config.openvpn_args).stop)
ip('addr', my_ip, 'dev', config.main_interface) ip('addr', my_ip, 'dev', config.main_interface)
if_rt = ['ip', '-6', 'route', 'del', if_rt = ['ip', '-6', 'route', 'del',
...@@ -253,7 +253,7 @@ def main(): ...@@ -253,7 +253,7 @@ def main():
os.path.join(config.log, 'babeld.log'), os.path.join(config.log, 'babeld.log'),
os.path.join(config.state, 'babeld.state'), os.path.join(config.state, 'babeld.state'),
config.babel_pidfile, tunnel_interfaces, config.babel_pidfile, tunnel_interfaces,
*config.babel_args).terminate) *config.babel_args).stop)
if config.up: if config.up:
r = os.system(config.up) r = os.system(config.up)
if r: if r:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment