closeio/tasktiger

Call atexit() handlers

Opened this issue · 2 comments

Since tasktiger forks a subprocess per task, it should call atexit handlers so that applications can properly cleanup before exiting.

For example, right now if using Segment's analytics package (e.g. analytics.track(...)) within a TaskTiger task, you must remember to call analytics.flush(). https://segment.com/docs/sources/server/python/#how-do-i-flush-right-now-.

This however would be done automatically since Segment normally flushes on its own when atexit is called.

We probably don't want to just call sys.exit() instead of os._exit() since it may have undesired side-effects (some exit handlers would be called multiple times: when the fork exits, and when TaskTiger exits).

In Python 2.7 we could:

  1. Store all the atexit._exithandlers before we fork (e.g. the length of the array – we just need to know which ones not to execute)
  2. Explicitly execute any atexit._exithandlers that were added while the task was executing
  3. Exit the task process with os._exit() the same way we do now.

There's also sys.exitfunc but we shouldn't support it because it was deprecated since version 2.4.

In Python 3.x we can't do that because atexit() is a built-in module (http://bugs.python.org/issue1680961). We could do the following in Python 3.x:

  1. After forking, from atexit import _clear and _clear()
  2. Before exiting the task, from atexit import _run_exitfuncs and _run_exitfuncs(). Or, just call sys.exit() assuming there are no other side-effects.

Related to #34