I've been asked to create a dbus interface to a program that uses SocketCAN to communicate to a set of control units on a car (that's just background info and not relevant to the question). The original concept was to use a listener interface that spawned a new "node" for each control unit being interrogated in the car. This would lead to something like the following objects on the com.acme.myservice
bus:
/com/acme/listener
/com/acme/node1
/com/acme/node2
...
/com/acme/nodeN
The idea is to take over the code from a C program that already communicates from the command line with a single ECU. That code depends on fork()ing in order to run parts of the communication cyclically and other parts in parallel for timing reasons.
I had planned on using the GDBusObjectManager model using new code for the listener and reusing the fork()ing code for each node instance. Unfortunately I ran into trouble because I still need to process DBus messages and relay the information to the (now forked) children and that's not supported:
On UNIX, the GLib mainloop is incompatible with fork(). Any program using the mainloop must either exec() or exit() from the child without returning to the mainloop.
I could restructure the forking code so that it executes in a single process in between iterations of the main loop instead of using g_main_loop_run but this will probably cause too much latency if there's a significant amount of data and multiple nodes running.
What's the best way around this? Is it possible to somehow handle these parallel items with a built-in glib mechanism or is there a way around the mainloop/forking issue? Is the only solution to use a different IPC mechanism between a single process using DBus and forked children doing the actual work? (This would probably be as much code as needed for the gdbus interface so it makes it sort of redundant)