def test_send_signal(self):
code = 'import time; print("sleeping", flush=True); time.sleep(3600)'
args = [sys.executable, '-c', code]
create = asyncio.create_subprocess_exec(*args,
stdout=subprocess.PIPE,
loop=self.loop)
proc = self.loop.run_until_complete(create)
@asyncio.coroutine
def send_signal(proc):
# basic synchronization to wait until the program is sleeping
line = yield from proc.stdout.readline()
self.assertEqual(line, b'sleeping\n')
proc.send_signal(signal.SIGHUP)
returncode = (yield from proc.wait())
return returncode
returncode = self.loop.run_until_complete(send_signal(proc))
self.assertEqual(-signal.SIGHUP, returncode)
python类SIGHUP的实例源码
def close(self, force=True):
'''This closes the connection with the child application. Note that
calling close() more than once is valid. This emulates standard Python
behavior with files. Set force to True if you want to make sure that
the child is terminated (SIGKILL is sent if the child ignores SIGHUP
and SIGINT). '''
if not self.closed:
self.flush()
self.fileobj.close() # Closes the file descriptor
# Give kernel time to update process status.
time.sleep(self.delayafterclose)
if self.isalive():
if not self.terminate(force):
raise PtyProcessError('Could not terminate the child.')
self.fd = -1
self.closed = True
#self.pid = None
def run_daemon(cmd, user=None):
LOG.info("Starting daemon")
rendered_cmd = jinja_render_cmd(cmd)
proc = execute_cmd(rendered_cmd, user)
# add signal handler
def sig_handler(signum, frame):
LOG.info("Caught a signal: %d", signum)
proc.send_signal(signum)
if signum == signal.SIGHUP:
time.sleep(5)
if proc.poll() is None:
LOG.info("Service restarted")
signal.signal(signal.SIGHUP, sig_handler)
signal.signal(signal.SIGINT, sig_handler)
signal.signal(signal.SIGTERM, sig_handler)
# wait for 5 sec and check that process is running
time.sleep(5)
if proc.poll() is None:
LOG.info("Daemon started")
return proc
proc.communicate()
raise RuntimeError("Process exited with code: %d" % proc.returncode)
def test_sighup(self):
self.assert_everything_has_started()
os.kill(self.subp.pid, signal.SIGHUP)
time.sleep(0.5)
lines = sorted(self.get_lines(6))
lines = self.hide_pids(lines)
self.assertEqual([
b'DEBUG:cotyledon._service:Run service light(0) [XXXX]',
b'ERROR:cotyledon.tests.examples:heavy reload',
b'ERROR:cotyledon.tests.examples:heavy reload',
b'ERROR:cotyledon.tests.examples:master reload hook',
b'INFO:cotyledon._service:Caught SIGTERM signal, '
b'graceful exiting of service light(0) [XXXX]',
b'INFO:cotyledon._service_manager:Child XXXX exited with status 0'
], lines)
os.kill(self.subp.pid, signal.SIGINT)
time.sleep(0.5)
self.assert_everything_is_dead(1)
def __init__(self, master=False):
# Setup signal fd, this allows signal to behave correctly
if os.name == 'posix':
self.signal_pipe_r, self.signal_pipe_w = os.pipe()
self._set_nonblock(self.signal_pipe_r)
self._set_nonblock(self.signal_pipe_w)
signal.set_wakeup_fd(self.signal_pipe_w)
self._signals_received = collections.deque()
signal.signal(signal.SIGINT, signal.SIG_DFL)
if os.name == 'posix':
signal.signal(signal.SIGCHLD, signal.SIG_DFL)
signal.signal(signal.SIGTERM, self._signal_catcher)
signal.signal(signal.SIGALRM, self._signal_catcher)
signal.signal(signal.SIGHUP, self._signal_catcher)
else:
# currently a noop on window...
signal.signal(signal.SIGTERM, self._signal_catcher)
# FIXME(sileht): should allow to catch signal CTRL_BREAK_EVENT,
# but we to create the child process with CREATE_NEW_PROCESS_GROUP
# to make this work, so current this is a noop for later fix
signal.signal(signal.SIGBREAK, self._signal_catcher)
def __init__(self):
""" class constructor
"""
# initially set an empty configuration
self.set_config(configparser.ConfigParser())
# set up the quit signals
self.setup_signals(
signals = [signal.SIGINT, signal.SIGTERM, signal.SIGHUP],
handler = self.quit
)
# can't use Gtk.main() because of a bug that prevents proper SIGINT
# handling. use Glib.MainLoop() directly instead.
self.mainloop = GLib.MainLoop() # main loop
##################
### Properties ###
##################
def close(self, force=True):
'''This closes the connection with the child application. Note that
calling close() more than once is valid. This emulates standard Python
behavior with files. Set force to True if you want to make sure that
the child is terminated (SIGKILL is sent if the child ignores SIGHUP
and SIGINT). '''
if not self.closed:
self.flush()
self.fileobj.close() # Closes the file descriptor
# Give kernel time to update process status.
time.sleep(self.delayafterclose)
if self.isalive():
if not self.terminate(force):
raise PtyProcessError('Could not terminate the child.')
self.fd = -1
self.closed = True
#self.pid = None
def reload(self):
"""Reload and re-apply configuration settings.
Existing child processes are sent a SIGHUP signal and will exit after
completing existing requests. New child processes, which will have the
updated configuration, are spawned. This allows preventing
interruption to the service.
"""
def _has_changed(old, new, param):
old = old.get(param)
new = getattr(new, param)
return (new != old)
old_conf = self.stash_conf_values()
has_changed = functools.partial(_has_changed, old_conf, self.conf)
cfg.CONF.reload_config_files()
os.killpg(self.pgid, signal.SIGHUP)
self.stale_children = self.children
self.children = set()
# Ensure any logging config changes are picked up
logging.setup(cfg.CONF, self.name)
self.configure_socket(old_conf, has_changed)
self.start_wsgi()
def close (self, force=True): # File-like object.
"""This closes the connection with the child application. Note that
calling close() more than once is valid. This emulates standard Python
behavior with files. Set force to True if you want to make sure that
the child is terminated (SIGKILL is sent if the child ignores SIGHUP
and SIGINT). """
if not self.closed:
self.flush()
os.close (self.child_fd)
time.sleep(self.delayafterclose) # Give kernel time to update process status.
if self.isalive():
if not self.terminate(force):
raise ExceptionPexpect ('close() could not terminate the child using terminate()')
self.child_fd = -1
self.closed = True
#self.pid = None
def config_monitor():
old_config = utils.read_file_text('config.json')
if not len(old_config):
logger.error("Could not read config.json file... not starting config monitor")
return
try:
mod_time = os.path.getmtime('config.json')
logger.debug("Started config monitor for config.json")
while True:
time.sleep(60)
if os.path.getmtime('config.json') != mod_time:
logger.debug("config.json was modified, restarting in 3 seconds...")
time.sleep(3)
os.kill(os.getppid(), signal.SIGHUP)
except Exception as ex:
logger.exception("Exception occurred: ")
############################################################
# PROCESS STUFF
############################################################
def __init__(self):
# process command line options and load config files
self._config = Config()
self._threads = []
self._exiting = False
self._reload = False
# signal handling
for sig, action in (
(signal.SIGINT, self.shutdown),
(signal.SIGQUIT, self.shutdown),
(signal.SIGTERM, self.shutdown),
(signal.SIGHUP, lambda s, f: setattr(self, '_reload', True)),
(signal.SIGPIPE, signal.SIG_IGN),
):
try:
signal.signal(sig, action)
except AttributeError:
pass
log.trace(self._config)
def __init__(self):
# process command line options and load config files
self._config = Config()
self._threads = []
self._exiting = False
self._reload = False
# signal handling
for sig, action in (
(signal.SIGINT, self.shutdown),
(signal.SIGQUIT, self.shutdown),
(signal.SIGTERM, self.shutdown),
(signal.SIGHUP, lambda s, f: setattr(self, '_reload', True)),
(signal.SIGPIPE, signal.SIG_IGN),
):
try:
signal.signal(sig, action)
except AttributeError:
pass
log.trace(self._config)
def signal_handler_unix(_signal, _frame):
"""
Manage system signals
:param _signal: The Posix signal See: http://pubs.opengroup.org/onlinepubs/009695399/
:param _frame: Unused, interrupted stack frame.
"""
_reason = None
if _signal == signal.SIGHUP:
_reason = 'Got SIGTERM, restarting..'
stop_handler(_reason, _restart=True)
else:
if _signal == signal.SIGQUIT:
_reason = 'Ctrl+D pressed, shutting down..'
elif _signal == signal.SIGINT:
_reason = 'Ctrl+C pressed, shutting down..'
elif _signal == signal.SIGTERM:
_reason = 'Got SIGTERM, shutting down..'
stop_handler(_reason)
def register_signals(_stop_handler):
"""
Register a callback to gracefully handle the system being externally shut down (terminated)
:param _stop_handler: A callback that helps the system shut down gracefully.
"""
if _stop_handler:
global stop_handler
stop_handler = _stop_handler
else:
raise Exception("No stop handler, probably an internal error, needed for graceful shut down.")
if os.name == "nt":
try:
import win32api
except ImportError:
version = ".".join(map(str, sys.version_info[:2]))
raise Exception("pywin32 not installed for Python " + version)
else:
win32api.SetConsoleCtrlHandler(signal_handler_windows, True)
write_to_log("Registered win32 ctrl handler", _category=EC_SERVICE, _severity=SEV_INFO)
else:
signal.signal(signal.SIGINT, signal_handler_unix)
signal.signal(signal.SIGTERM, signal_handler_unix)
signal.signal(signal.SIGQUIT, signal_handler_unix)
signal.signal(signal.SIGHUP, signal_handler_unix)
def start(self):
"""start method is where we decide to :
* catch term signal
* run as daemon
* start the http server
"""
self.log.info("CacheServer starting ...")
# catch SIG_TERM
gevent.signal(signal.SIGTERM, self.sig_term)
gevent.signal(signal.SIGHUP, self.sig_hup)
# run
self._run = True
if self._daemon:
self.do_daemon()
# start http server
self.log.info("CacheServer started at: 'http://%s'" % self.http_address)
# Start cache server
try:
self.http_server.serve_forever()
except (SystemExit, KeyboardInterrupt):
pass
# finish here
self.log.info("CacheServer Exited")
def reload(self, log_file=None, dump_stack_trace=False):
print ('== RELOAD IS BUGGY ==')
pid = self.pid
if pid:
try:
int(pid) # "if pid is int". If not, an exception will be rised.
os.kill(pid, signal.SIGHUP)
time.sleep(5) # trochu hack, mozna by byl lepsi nejaky cyklus co kontroluje ukonceni daneho pidu, nebo tak neco
# POZOR NEFUNGUJE SPRAVNE, NESTIHNE SE UKONCIT A NOVY SE NESPUSTI
self.start(log_file=log_file, dump_stack_trace=dump_stack_trace)
except ValueError:
print("The content of the pidfile is invalid!")
print(pid)
else:
print ('Not Running')
def close(self, force=True):
'''This closes the connection with the child application. Note that
calling close() more than once is valid. This emulates standard Python
behavior with files. Set force to True if you want to make sure that
the child is terminated (SIGKILL is sent if the child ignores SIGHUP
and SIGINT). '''
if not self.closed:
self.flush()
os.close(self.child_fd)
# Give kernel time to update process status.
time.sleep(self.delayafterclose)
if self.isalive():
if not self.terminate(force):
raise ExceptionPexpect('Could not terminate the child.')
self.child_fd = -1
self.closed = True
#self.pid = None
def close(self, force=True):
'''This closes the connection with the child application. Note that
calling close() more than once is valid. This emulates standard Python
behavior with files. Set force to True if you want to make sure that
the child is terminated (SIGKILL is sent if the child ignores SIGHUP
and SIGINT). '''
if not self.closed:
self.flush()
self.fileobj.close() # Closes the file descriptor
# Give kernel time to update process status.
time.sleep(self.delayafterclose)
if self.isalive():
if not self.terminate(force):
raise PtyProcessError('Could not terminate the child.')
self.fd = -1
self.closed = True
#self.pid = None
def close(self, force=True):
'''This closes the connection with the child application. Note that
calling close() more than once is valid. This emulates standard Python
behavior with files. Set force to True if you want to make sure that
the child is terminated (SIGKILL is sent if the child ignores SIGHUP
and SIGINT). '''
if not self.closed:
self.flush()
self.fileobj.close() # Closes the file descriptor
# Give kernel time to update process status.
time.sleep(self.delayafterclose)
if self.isalive():
if not self.terminate(force):
raise PtyProcessError('Could not terminate the child.')
self.fd = -1
self.closed = True
#self.pid = None
def test_send_signal(self):
code = 'import time; print("sleeping", flush=True); time.sleep(3600)'
args = [sys.executable, '-c', code]
create = asyncio.create_subprocess_exec(*args,
stdout=subprocess.PIPE,
loop=self.loop)
proc = self.loop.run_until_complete(create)
@asyncio.coroutine
def send_signal(proc):
# basic synchronization to wait until the program is sleeping
line = yield from proc.stdout.readline()
self.assertEqual(line, b'sleeping\n')
proc.send_signal(signal.SIGHUP)
returncode = (yield from proc.wait())
return returncode
returncode = self.loop.run_until_complete(send_signal(proc))
self.assertEqual(-signal.SIGHUP, returncode)
def close(self, force=True):
'''This closes the connection with the child application. Note that
calling close() more than once is valid. This emulates standard Python
behavior with files. Set force to True if you want to make sure that
the child is terminated (SIGKILL is sent if the child ignores SIGHUP
and SIGINT). '''
if not self.closed:
self.flush()
os.close(self.child_fd)
# Give kernel time to update process status.
time.sleep(self.delayafterclose)
if self.isalive():
if not self.terminate(force):
raise ExceptionPexpect('Could not terminate the child.')
self.child_fd = -1
self.closed = True
#self.pid = None
def signalhandler(signum, _):
"""
Signal handler to close and reopen log file(s) on HUP
and exit on KILL.
"""
if signum == signal.SIGHUP:
global logger
logger.info("SIGHUP received; reopening log files.")
nav.logs.reopen_log_files()
nav.daemon.redirect_std_fds(
stderr=nav.logs.get_logfile_from_logger())
logger.info("Log files reopened.")
elif signum == signal.SIGTERM:
logger.warning('SIGTERM received: Shutting down.')
sys.exit(0)
def __init__(self, **kwargs):
signal.signal(signal.SIGHUP, self.signalhandler)
signal.signal(signal.SIGTERM, self.signalhandler)
self.config = config.pingconf()
init_generic_logging(stderr=True, read_config=True)
self._isrunning = 1
self._looptime = int(self.config.get("checkinterval", 60))
LOGGER.info("Setting checkinterval=%i", self._looptime)
self.db = db.db()
sock = kwargs.get("socket", None)
self.pinger = megaping.MegaPing(sock)
self._nrping = int(self.config.get("nrping", 3))
# To keep status...
self.netboxmap = {} # hash netboxid -> netbox
self.down = [] # list of netboxids down
self.replies = {} # hash netboxid -> circbuf
self.ip_to_netboxid = {}
def test_send_signal(self):
code = 'import time; print("sleeping", flush=True); time.sleep(3600)'
args = [sys.executable, '-c', code]
create = asyncio.create_subprocess_exec(*args, loop=self.loop, stdout=subprocess.PIPE)
proc = self.loop.run_until_complete(create)
@asyncio.coroutine
def send_signal(proc):
# basic synchronization to wait until the program is sleeping
line = yield from proc.stdout.readline()
self.assertEqual(line, b'sleeping\n')
proc.send_signal(signal.SIGHUP)
returncode = (yield from proc.wait())
return returncode
returncode = self.loop.run_until_complete(send_signal(proc))
self.assertEqual(-signal.SIGHUP, returncode)
def post(self, request):
"""
Request to restart all nginx threads
---
# Class Name : CommonServerRestart
# Description:
restart nginx threads via rest api
"""
try:
os.kill(os.getppid(), signal.SIGHUP)
return_data = {"status": "200", "result": "restart uwsgi"}
return Response(json.dumps(return_data))
except Exception as e:
return_data = {"status": "404", "result": str(e)}
return Response(json.dumps(return_data))
def test_SIGHUP_tty(self):
# When not daemonized, SIGHUP should shut down the server.
try:
from signal import SIGHUP
except ImportError:
return self.skip("skipped (no SIGHUP) ")
# Spawn the process.
p = helper.CPProcess(ssl=(self.scheme.lower() == 'https'))
p.write_conf(
extra='test_case_name: "test_SIGHUP_tty"')
p.start(imports='cherrypy.test._test_states_demo')
# Send a SIGHUP
os.kill(p.get_pid(), SIGHUP)
# This might hang if things aren't working right, but meh.
p.join()
def shutDown(signum, frame):
"""Signal handler for shutting down the server."""
print
print "App server has been signaled to shutdown."
if server and server._running > 2:
print "Shutting down at", asclocaltime()
sys.stdout.flush()
server._running = 2
if signum == SIGINT:
raise KeyboardInterrupt
elif signum == SIGHUP:
sys.exit(3) # force reload
else:
sys.exit(0) # normal exit
else:
print "No running app server was found."
def finish_read(self, timeout=2, stdin_content="", stdin=False):
"""
Wait until we got output or until timeout is over
"""
process = Thread(target=self.get_output, args=(stdin_content, stdin))
process.start()
if timeout > 0:
process.join(timeout)
else:
process.join()
if process.is_alive():
self.close()
self.return_code = -signal.SIGHUP
else:
self.return_code = self.process.returncode
def set_graceful_exit():
"""
Set up a graceful exit when certain signals arrive.
"""
for sig in [signal.SIGHUP,
signal.SIGINT,
signal.SIGQUIT,
signal.SIGTERM]:
signal.signal(sig, __exit_handler)
def _installSignalHandlers(self):
supportedSignals = [signal.SIGINT, signal.SIGTERM]
if hasattr(signal, 'SIGHUP'):
supportedSignals.append(signal.SIGHUP)
self._oldSIGs = [(x,signal.getsignal(x)) for x in supportedSignals]
for sig in supportedSignals:
if hasattr(signal, 'SIGHUP') and sig == signal.SIGHUP:
signal.signal(sig, self._hupHandler)
else:
signal.signal(sig, self._intHandler)