Using GDBus with code that uses fork() - c

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)

Related

GLib: how to quit main loop automatically started by g_initable_new()?

My excuses for the newbie question:
I used gdbus-codegen to generate a C-code D-Bus client proxy, running on a Yocto Linux embedded system. The generated code calls g_initable_new(), returning a GInitable *.
At this point, two new threads appear: from the stack trace, I see that one calls g_main_loop_run(), and the other g_main_context_iteration(). So I gather that under the hood, g_initable_new() started a new main loop. OK so far.
When I'm done, I call g_object_unref() on my GInitable *. That works too, but the two threads are still running. How do I quit that loop?
Thanks in advance!
As the other #Philip confirmed, GDBus creates worker threads that can apparently not be stopped. Boo hiss.
My initial concern was that I didn't want my child process to inherit some useless - and potentially harmful - threads. But actually, fork() takes care of that, as noted in the manpage: "The child process is created with a single thread — the one that called fork()." So this concern is unfounded.
But I discovered another good reason to spawn the D-Bus code: I have a setuid program, and as soon as I call setreuid() to reduce the privileges of my process, the gdbus worker threads fail (which makes sense).
So that appears to be my answer: you can't quit the GDBus worker threads, and if that's not OK, isolate the GDBus stuff in a process of its own.

executing slow process with popen()

I'm creating a simple network scanning function using nmap and C. I want to use popen() to execute nmap, but nmap takes close to 30 seconds to complete because I'm scanning a wide range of IPs.
So, is there a way to check when the command has finished executing? I don't want my C code to hang at the system call, instead I would like to just check a flag or something in a loop that will know when popen/nmap has finished so other parts of my C program don't come to an halt. Is this possible??
Thanks!
I can think of 2 direct ways to do it
You could fork() directly and then establish a way to communicate the two processes, this would be very difficult because IPC is not an easy matter.
You could create a new thread with pthread_create() and call popen() there, it would be a lot easier and you could share data between threads by using an appropriate locking mechanism to prevent race conditions.
You can either use multi processing with fork (hardmode)
Or you can use multithreading using pthread (easymode)
Either one allows you to do 2 things at once. Multiprocessing is hard because you must worry about innerproccess communications (pipes) and the 2 tasks you're trying to do can not share memory.
Multithreading is a much more easy because all you need is to include the libraries (-lpthread) and then specify what function is on the seperate thread.

Splitting a large multi-thread binary into smaller individual processes/binaries

I'm not sure if the title accurately describes what I want to do but here's the rub:
We have a large and hairy codebase (not-invented-here courtesy of Elbonian Code Slaves) which currently compiles as one big binary which internally creates several pthreads for various specific tasks, communicating through IPC messages.
It's not ideal for a number of reasons, and several of the threads would be better as independent autonomous processes as they are all individual specific "workers" rather than multiple instances of the same piece of code.
I feel a bit like I'm missing some trick, is our only option to split off the various thread code and compile each as a standalone executable invoked using system() or exec() from the main blob of code? It feels clunky somehow.
If you want to take a part of your program that currently runs as a thread, and instead run it as a separate process launched by your main program, then you have two main options:
Instead of calling pthread_create(), fork() and in the child process call the thread-start function directly (do not use any of the exec-family functions).
Compile the code that the the thread executes as a separate executable. Launch that executable at need by the standard fork / exec sequence. (Or you could use system() instead of fork/exec, but don't. Doing so needlessly brings the shell into it, and also gives you much less control.)
The former has the disadvantage that each process image contains a lot of code that it will never use, since each is a complete copy of everything. Inasmuch as under Linux fork() uses copy-on-write, however, that's mostly an address-space issue, not a resource-wastage issue.
The latter has the disadvantage that the main program needs to be able to find the child programs on the file system. That's not necessarily a hard problem, mind you, but it is substantially different from already having the needed code at hand. If there is any way that any of the child programs would be independently useful, however, then breaking them out as separate programs makes a fair amount of sense.
Do note, by the way, that I do not in general accept your premise that it is inappropriate to implement specific for-purpose workers as threads. If you want to break out such tasks, however, then the above are your available alternatives.
Edited to add:
As #EOF pointed out, if you intend that after the revamp your main process will still be multi-threaded (that is, if you intend to convert only some threads to child processes) then you need to be aware of a significant restriction placed by POSIX:
If a multi-threaded process calls fork(), [...] to avoid errors, the child process may only execute async-signal-safe operations until such time as one of the exec functions is called.
On the other hand, I'm pretty sure the relevant definition of "multi-threaded" is that the process has multiple live threads at the time fork() is called. It should not present a problem if the child processes are all forked off before any additional threads are created, or after all but one thread is joined.

Recreate dead threads after a fork

As you might know, all threads in the application die in a forked process, other than the thread doing the fork. However, I plan to ressurrect those threads in the forked process by calling pthread_create and using pthread_attr_setstack, so as to assign the newly created threads the same stack as the dead threads. Something like as follows.
// stackAddr and stacksize taken from the dead thread
pthread_attr_setstack(&attr, stackAddr, stacksize);
rc = pthread_create(&thread, &attr, threadRoutine, NULL);
However, I would still need to get the CPU register values, such as stack pointer, base pointer, instruction pointer etc, to restart threads from the same point. How can I do that? And what else do I need to do to successfully achieve my goal?
Also note that I'm using a 64-bit architecture. What additional difficulties would it have as compared to 32-bit one?
I see two possible ways to shoot yourself in the foot and lose hair^W^W^W^W^W^W^W^Wtry to do this:
Try to force each thread into calling getcontext() before the fork(), and then restore the context of each thread via setcontext(). Probably won't work, but you can try for fun.
Save ptrace(PTRACE_GETREGS), ptrace(PTRACE_GETFPREGS), and restore with ptrace(PTRACE_SETREGS), ptrace(PTRACE_SETFPREGS).
The other threads in the current process aren't killed by a fork -- they're still there and running in the parent. The problem you seem to have is that fork only forks a SINGLE thread in the current procces, creating a new process running one thread with a copy of all non-thread resources in the parent.
What you apparently want is a way of duplicating an entire multithreaded task, forking all the threads in it and creating a new process/task with the same number of threads.
In order to do THAT, you would need to find and pause all the other threads in the process, dump their current state (including all locks they hold), fork a new process, and then (re)create each of those other threads in the child, rewiring the lock state to refer to the new child threads where needed.
Unfortunately, the POSIX pthread interface is hopelessly underspecified, and provides no way of doing that. In particular, it lacks any sort of reflective interface allowing you to figure out what threads are actually running.
If you want to try to do this anyway, I can see two ways of trying to approach this:
poke around in /proc/self/task to figure out what threads are running in your process, effectively getting that reflective interface in a highly non-portable way. You'll likely end up having to ptrace(2) the other threads to get their internal state. This will be very difficult.
wrap the pthreads library -- instead of using library directly, intercept every call and keep track of all the threads/mutexes/locks that get created, so that you have that information available when you want to fork. This will work fine as long as you don't want to use any third-party libraries that use pthreads
The second option is much easier (and somewhat portable), but only works well if you have access to all the source code of your entire application, and can modify it to use your wrappers properly.
Just googling around I found that solaris has a forkall() call that does exactly what you want, see the documentation here:
http://download.oracle.com/docs/cd/E19963-01/html/821-1601/gen-1.html
I assume you're running on linux, but it is possible to run solaris on x86 hardware. So maybe that is an option for you.

Is there a way to ‘join’ (block) in POSIX threads, without exiting the joinee?

I’m buried in multithreading / parallelism documents, trying to figure out how to implement a threading implementation in a programming language I’ve been designing.
I’m trying to map a mental model to the pthreads.h library, but I’m having trouble with one thing: I need my interpreter instances to continue to exist after they complete interpretation of a routine (the language’s closure/function data type), because I want to later assign other routines to them for interpretation, thus saving me the thread and interpreter setup/teardown time.
This would be fine, except that pthread_join(3) requires that I call pthread_exit(3) to ‘unblock’ the original thread. How can I block the original thread (when it needs the result of executing the routine), and then unblock it when interpretation of the child routine is complete?
Use a pthread_cond_t; wait on it on one thread and signal or broadcast it in the other.
Sounds like you actually want an implementation of the Thread Pool Pattern. It makes for a fairly simple conceptual model, without repeated thread creation & tear down costs. Some OS's directly support it, on others it should be reasonably simple to implement using a queue and a semaphore.

Resources