Context manager, atexit processing, and PEP 3143 DaemonContext.close
ben+python at benfinney.id.au
Sun May 17 02:50:23 CEST 2009
I'm slowly developing PEP 3143 and, in parallel, its reference
implementation, the ‘python-daemon’ library
<URL:http://pypi.python.org/pypi/python-daemon/>. Feedback continues to
be welcome from people wanting to make a program become a daemon; please
try it out and critique the specification and/or the implementation.
Today a flaw has been uncovered by Pavol Babinčák. In diagnosing an
issue, we doscovered that PEP 3143 currently leads, in some common
circumstances, to exiting a context manager twice.
The current specification of the `DaemonContext` class says:
Close the daemon context. This performs the following step:
* If the pidfile attribute is not None, exit its context
__exit__(exc_type, exc_value, exc_traceback)
Return: True or False as defined by the context manager
Call the instance's close() method, then return True if the
exception was handled or False if it was not.
Open the daemon context, turning the current program into a daemon
process. This performs the following steps:
* Register the close method to be called during Python's exit
This leads to the situation where the `DaemonContext.close` method can
be called twice:
pidfile = FunkyLockFile()
daemon_context = daemon.DaemonContext(pidfile=pidfile)
According to the current specification, this will cause
`daemon_context.close()` to be called on exiting its context manager (at
the end of the `with` suite) *and* on program exit (via `atexit`
This will cause the `pidfile` context manager to be exited twice in
succession, which surely can't be good and is at least undefined AFAICT.
How should a context manager be implemented to handle situations like
this? One possible way is to raise an exception when trying to close a
not-open context manager. Another is to return immediately if the
attempt is made, making it safe to try closing a context manager
The “Register the close method to be called during Python's exit
processing” is there to ensure clean-up occurs even if the program
isn't using the DaemonContext as a context manager. Ideally, what I'd
like to do is *un*-register the `close` method after having already
closed it, so that exit processing *won't* call it. The `atexit` module,
though, doesn't appear to give me that option.
Ideas? How should this be addressed both Pythonically and respecting the
intent of PEP 3143?
\ “For fast acting relief, try slowing down.” —Jane Wagner, via |
`\ Lily Tomlin |
More information about the Python-list