mathutil: Disable queuelogger in background_coordinate_descent()

If the queuelogger was holding the lock when the process is forked
then any attempt to log from the background process would result in a
deadlock.  Attempt a workaround by disabling the queuelogger at the
start of the background process.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2019-12-17 09:51:45 -05:00
parent d9cd524aec
commit abf493496c
2 changed files with 17 additions and 4 deletions

View File

@ -1,9 +1,10 @@
# Simple math helper functions # Simple math helper functions
# #
# Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net> # Copyright (C) 2018-2019 Kevin O'Connor <kevin@koconnor.net>
# #
# This file may be distributed under the terms of the GNU GPLv3 license. # This file may be distributed under the terms of the GNU GPLv3 license.
import math, logging, multiprocessing, traceback import math, logging, multiprocessing, traceback
import queuelogger
###################################################################### ######################################################################
@ -51,6 +52,7 @@ def coordinate_descent(adj_params, params, error_func):
def background_coordinate_descent(printer, adj_params, params, error_func): def background_coordinate_descent(printer, adj_params, params, error_func):
parent_conn, child_conn = multiprocessing.Pipe() parent_conn, child_conn = multiprocessing.Pipe()
def wrapper(): def wrapper():
queuelogger.clear_bg_logging()
try: try:
res = coordinate_descent(adj_params, params, error_func) res = coordinate_descent(adj_params, params, error_func)
except: except:

View File

@ -1,6 +1,6 @@
# Code to implement asynchronous logging from a background thread # Code to implement asynchronous logging from a background thread
# #
# Copyright (C) 2016,2017 Kevin O'Connor <kevin@koconnor.net> # Copyright (C) 2016-2019 Kevin O'Connor <kevin@koconnor.net>
# #
# This file may be distributed under the terms of the GNU GPLv3 license. # This file may be distributed under the terms of the GNU GPLv3 license.
import logging, logging.handlers, threading, Queue, time import logging, logging.handlers, threading, Queue, time
@ -52,10 +52,21 @@ class QueueListener(logging.handlers.TimedRotatingFileHandler):
self.emit(logging.makeLogRecord( self.emit(logging.makeLogRecord(
{'msg': "\n".join(lines), 'level': logging.INFO})) {'msg': "\n".join(lines), 'level': logging.INFO}))
MainQueueHandler = None
def setup_bg_logging(filename, debuglevel): def setup_bg_logging(filename, debuglevel):
global MainQueueHandler
ql = QueueListener(filename) ql = QueueListener(filename)
qh = QueueHandler(ql.bg_queue) MainQueueHandler = QueueHandler(ql.bg_queue)
root = logging.getLogger() root = logging.getLogger()
root.addHandler(qh) root.addHandler(MainQueueHandler)
root.setLevel(debuglevel) root.setLevel(debuglevel)
return ql return ql
def clear_bg_logging():
global MainQueueHandler
if MainQueueHandler is not None:
root = logging.getLogger()
root.removeHandler(MainQueueHandler)
root.setLevel(logging.WARNING)
MainQueueHandler = None