Skip to content

Shutdown never confirms the process died, and leaks it if it did not #50

Description

@sequoiap

pyrolab/manager.py:584-598:

def shutdown_nameserver(self, nameserver: str) -> bool:
    group = self.nameservers.pop(nameserver)   # forgotten before it is dead
    polling = group.process.msg_polling
    group.msg_queue.put(None)
    time.sleep(2 * polling)                    # fixed 2s, then assume success
    return True                                # unconditional

(shutdown_daemon is identical.) There is no join(), no is_alive() check, no terminate() escalation, and no way for the return value to be False.

Impact. The kill signal is delivered over a queue that the child only reads in a polling timer thread. A daemon wedged inside a blocking C call -- a Kinesis DLL call, a VISA read, the unbounded while True in the Arduino driver -- never processes the message. The process survives, still holding its TCP port and its exclusive handle on the hardware, but the manager has already popped it from self.daemons and will never look at it again. It is orphaned until the machine is rebooted.

This is the one place that most needs a hard kill and it is the one place that has none. It also makes pyrolab down and pyrolab reload unreliable in exactly the situation where you reach for them.

Suggested fix: escalate and confirm, and only then forget the entry:

group.msg_queue.put(None)
group.process.join(timeout)
if group.process.is_alive():
    log.warning("...did not exit, terminating")
    group.process.terminate()
    group.process.join(5)
if group.process.is_alive():
    group.process.kill()
    group.process.join()
alive = group.process.is_alive()
self.daemons.pop(daemon, None)
return not alive

The fixed time.sleep(2 * polling) also blocks the pyrolabd Pyro request thread for 2 seconds per entity, making pyrolab down slow in proportion to how much is running.


Found in a full-codebase audit at v0.4.0 (commit 1ce3146).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions