Skip to content

Problem: zsys_init() + fork() causes unxpected behavior #1659

@jpitc

Description

@jpitc

Background

The application I'm working on explicitly requires process isolation, so I'm not using threads. The child processes never exec(), also for good reason. I'm working with the git for upcoming CZMQ 4.0.3.

Problem

Very early, the parent creates a logging socket for the child processes to connect to after it is spawned. I've been experiencing all manner of strange behavior by the child processes with this pattern.

Things I've Tried

  • The child calls zsock_destroy() on all the parents sockets when it starts (just as it would close pipe fd's), this is the proper thing to do but doesn't solve the problem.
  • I've tried calling zsys_shutdown() first thing in the child to wipe the slate clean, but any subsequent call to czmq triggers zsys_init() then fails with assert(!s_process_ctx).
  • I've NULL'ed the pointer after its freed and got a malloc SEGV due to a double free... and so on.

Diagnosis

zsys.c constains a non-trivial amount of mutable global state. When almost any czmq call is made, that global state is modified, and zsys_shutdown() does not restore it. a subsequent call to zsys_init() then encounters an undefined initial state and bad things happen.

Proposed solution

I've added a new internal (static) zsys_reset() function which restores all global state to initial values, which zsys_shutdown() calls it as its (nearly) final act. This change has reNew contributorsolved all the issues I've seen. So far.

Points For Discussion

  • CLASS destructors NULL references after they are freed, but zsys_shutdown() doesn't follow this
    pattern for zsys.c global state. Possibly this needs to be cleaned up in the entire tree. Haven't looked.
  • My solution duplicates the static initialization of global state into the zsys_reset() code, which is a brittle. If someone in the future adds a some more global state and forgets to update zsys_reset()...
  • There may be other global state outside zsys, which would complicate matter. Guidance from principles welcome.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions