Fix 'utime went backwards' errors on daemonization. (#5609)

* Fix 'utime went backwards' errors on daemonization.

Fixes #5608

* remove spurious debug
This commit is contained in:
Richard van der Hoff 2019-07-03 13:40:45 +01:00 committed by Amber Brown
parent 463d5a8fde
commit cb8d568cf9
3 changed files with 42 additions and 29 deletions

1
changelog.d/5609.bugfix Normal file
View file

@ -0,0 +1 @@
Fix 'utime went backwards' errors on daemonization.

View file

@ -93,33 +93,36 @@ def start_reactor(
install_dns_limiter(reactor) install_dns_limiter(reactor)
def run(): def run():
# make sure that we run the reactor with the sentinel log context, logger.info("Running")
# otherwise other PreserveLoggingContext instances will get confused change_resource_limit(soft_file_limit)
# and complain when they see the logcontext arbitrarily swapping if gc_thresholds:
# between the sentinel and `run` logcontexts. gc.set_threshold(*gc_thresholds)
with PreserveLoggingContext(): reactor.run()
logger.info("Running")
change_resource_limit(soft_file_limit) # make sure that we run the reactor with the sentinel log context,
if gc_thresholds: # otherwise other PreserveLoggingContext instances will get confused
gc.set_threshold(*gc_thresholds) # and complain when they see the logcontext arbitrarily swapping
reactor.run() # between the sentinel and `run` logcontexts.
#
# We also need to drop the logcontext before forking if we're daemonizing,
# otherwise the cputime metrics get confused about the per-thread resource usage
# appearing to go backwards.
with PreserveLoggingContext():
if daemonize:
if print_pidfile:
print(pid_file)
if daemonize: daemon = Daemonize(
if print_pidfile: app=appname,
print(pid_file) pid=pid_file,
action=run,
daemon = Daemonize( auto_close_fds=False,
app=appname, verbose=True,
pid=pid_file, logger=logger,
action=run, )
auto_close_fds=False, daemon.start()
verbose=True, else:
logger=logger, run()
)
daemon.start()
else:
run()
def quit_with_error(error_string): def quit_with_error(error_string):

View file

@ -52,6 +52,15 @@ except Exception:
return None return None
# get an id for the current thread.
#
# threading.get_ident doesn't actually return an OS-level tid, and annoyingly,
# on Linux it actually returns the same value either side of a fork() call. However
# we only fork in one place, so it's not worth the hoop-jumping to get a real tid.
#
get_thread_id = threading.get_ident
class ContextResourceUsage(object): class ContextResourceUsage(object):
"""Object for tracking the resources used by a log context """Object for tracking the resources used by a log context
@ -225,7 +234,7 @@ class LoggingContext(object):
# became active. # became active.
self.usage_start = None self.usage_start = None
self.main_thread = threading.current_thread() self.main_thread = get_thread_id()
self.request = None self.request = None
self.tag = "" self.tag = ""
self.alive = True self.alive = True
@ -318,7 +327,7 @@ class LoggingContext(object):
record.request = self.request record.request = self.request
def start(self): def start(self):
if threading.current_thread() is not self.main_thread: if get_thread_id() != self.main_thread:
logger.warning("Started logcontext %s on different thread", self) logger.warning("Started logcontext %s on different thread", self)
return return
@ -328,7 +337,7 @@ class LoggingContext(object):
self.usage_start = get_thread_resource_usage() self.usage_start = get_thread_resource_usage()
def stop(self): def stop(self):
if threading.current_thread() is not self.main_thread: if get_thread_id() != self.main_thread:
logger.warning("Stopped logcontext %s on different thread", self) logger.warning("Stopped logcontext %s on different thread", self)
return return
@ -355,7 +364,7 @@ class LoggingContext(object):
# If we are on the correct thread and we're currently running then we # If we are on the correct thread and we're currently running then we
# can include resource usage so far. # can include resource usage so far.
is_main_thread = threading.current_thread() is self.main_thread is_main_thread = get_thread_id() == self.main_thread
if self.alive and self.usage_start and is_main_thread: if self.alive and self.usage_start and is_main_thread:
utime_delta, stime_delta = self._get_cputime() utime_delta, stime_delta = self._get_cputime()
res.ru_utime += utime_delta res.ru_utime += utime_delta