Howdy all, 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() Return: None Close the daemon context. This performs the following step: * If the pidfile attribute is not None, exit its context manager. ===== and: ===== __exit__(exc_type, exc_value, exc_traceback) Return: True or False as defined by the context manager protocol Call the instance's close() method, then return True if the exception was handled or False if it was not. ===== but also: ===== open() Return: None 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 processing. ===== This leads to the situation where the `DaemonContext.close` method can be called twice: pidfile = FunkyLockFile() daemon_context = daemon.DaemonContext(pidfile=pidfile) with daemon_context: main_processing() 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` processing). 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 multiple times. 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 | _o__) | Ben Finney -- http://mail.python.org/mailman/listinfo/python-list