Start using asyncio for signals

This commit is contained in:
nemunaire 2017-07-18 07:18:06 +02:00 committed by nemunaire
commit c6b5aab917
3 changed files with 18 additions and 26 deletions

View file

@ -7,7 +7,7 @@ An extremely modulable IRC bot, built around XML configuration files!
Requirements Requirements
------------ ------------
*nemubot* requires at least Python 3.3 to work. *nemubot* requires at least Python 3.4 to work, as it uses `asyncio`.
Connecting to SSL server requires [this patch](http://bugs.python.org/issue27629). Connecting to SSL server requires [this patch](http://bugs.python.org/issue27629).

View file

@ -178,25 +178,13 @@ def main():
daemonize(args.socketfile, not args.no_attach) daemonize(args.socketfile, not args.no_attach)
# Signals handling # Signals handling
def sigtermhandler(signum, frame): def sigtermhandler():
"""On SIGTERM and SIGINT, quit nicely""" """On SIGTERM and SIGINT, quit nicely"""
context.quit() context.quit()
signal.signal(signal.SIGINT, sigtermhandler) context.loop.add_signal_handler(signal.SIGINT, sigtermhandler)
signal.signal(signal.SIGTERM, sigtermhandler) context.loop.add_signal_handler(signal.SIGTERM, sigtermhandler)
def sighuphandler(signum, frame): def sigusr1handler():
"""On SIGHUP, perform a deep reload"""
nonlocal context
logger.debug("SIGHUP receive, iniate reload procedure...")
# Reload configuration file
for path in args.files:
if os.path.isfile(path):
sync_act("loadconf", path)
signal.signal(signal.SIGHUP, sighuphandler)
def sigusr1handler(signum, frame):
"""On SIGHUSR1, display stacktraces""" """On SIGHUSR1, display stacktraces"""
import threading, traceback import threading, traceback
for threadId, stack in sys._current_frames().items(): for threadId, stack in sys._current_frames().items():
@ -208,24 +196,21 @@ def main():
logger.debug("########### Thread %s:\n%s", logger.debug("########### Thread %s:\n%s",
thName, thName,
"".join(traceback.format_stack(stack))) "".join(traceback.format_stack(stack)))
signal.signal(signal.SIGUSR1, sigusr1handler) context.loop.add_signal_handler(signal.SIGUSR1, sigusr1handler)
# Store PID to pidfile # Store PID to pidfile
if args.pidfile is not None: if args.pidfile is not None:
with open(args.pidfile, "w+") as f: with open(args.pidfile, "w+") as f:
f.write(str(os.getpid())) f.write(str(os.getpid()))
# context can change when performing an hotswap, always join the latest context context.start()
oldcontext = None context.loop.run_forever()
while oldcontext != context: context.join()
oldcontext = context
context.start()
context.join()
# Wait for consumers # Wait for consumers
logger.info("Waiting for other threads shuts down...") logger.info("Waiting for other threads shuts down...")
if args.debug: if args.debug:
sigusr1handler(0, None) sigusr1handler()
sys.exit(0) sys.exit(0)

View file

@ -14,6 +14,7 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import asyncio
from datetime import datetime, timezone from datetime import datetime, timezone
import logging import logging
from multiprocessing import JoinableQueue from multiprocessing import JoinableQueue
@ -40,7 +41,7 @@ class Bot(threading.Thread):
"""Class containing the bot context and ensuring key goals""" """Class containing the bot context and ensuring key goals"""
def __init__(self, ip="127.0.0.1", modules_paths=list(), def __init__(self, ip="127.0.0.1", modules_paths=list(),
data_store=datastore.Abstract(), debug=False): data_store=datastore.Abstract(), debug=False, loop=None):
"""Initialize the bot context """Initialize the bot context
Keyword arguments: Keyword arguments:
@ -59,6 +60,9 @@ class Bot(threading.Thread):
self.debug = debug self.debug = debug
self.stop = None self.stop = None
#
self.loop = loop if loop is not None else asyncio.get_event_loop()
# External IP for accessing this bot # External IP for accessing this bot
import ipaddress import ipaddress
self.ip = ipaddress.ip_address(ip) self.ip = ipaddress.ip_address(ip)
@ -522,6 +526,9 @@ class Bot(threading.Thread):
for cnsr in k: for cnsr in k:
cnsr.stop = True cnsr.stop = True
logger.info("Closing event loop")
self.loop.stop()
if self.stop is False or sync_queue is not None: if self.stop is False or sync_queue is not None:
self.stop = True self.stop = True
sync_act("end") sync_act("end")