The process management for the selector is based on an 'overseer' process. This process is necessary to address the following problems:
- no data space corruption in the X resources that are allocated in the main program after forking and exiting
- faster startup, since we don't need to duplicate that much file handles and other resources when a fork occurs
- the ALSA problem is solved. This problem occurs essentially because the alsalib does not provide a function to unlink a resource after it has been forked. As such, when an analysis process is running, which during the fork took a copy of the DSP handle that was used during fragment playing.. then the selector itself can no longer access the DSP driver, or could not close/open it any longer.
- signals no longer get lost, which was still a problem in the old code and a potential deadlock situation in the ToSwitchOrNotToSwitch signal has also been removed
Aside from these advantages. The centralized nature of this overseer process makes it possible for us to directly test a number of conditions which are otherwise difficult to check. See bos.cpp for a number of these tests
- multiple threads can concurrently ask to spawn processes.
- multiple threads can concurrently retrieve the process state.
The overseer itself forks of the main program and remains listening to requests to spawn a program. In return it will send back the exit code when the child dies. A side effect is as well that the process id's are assigned by the main client and automatically mapped to the real ids.
To debug applications that are using this overseer, one should resort to starting the application outside the debugger and then connecting to the second BpmDj instance (the real program, not the overseer) with
gdb ./bpmdj <pid>