Hook exit code with a dynamic library in C - c

I would like to write a dynamic library that catches exit code of a program and their possible child processes.
Is it possible without setting up signal handlers?

Related

C write async unsafe code in signal handler

How can i run asynchrounous-unsafe code in a signal handler. I cant use a flag in my case. Could i use longjmp to jump to a different context?
In a signal handler you can only use a set of safe functions which in many cases is sufficient for complicated functionality started within a handler. You can check man pages for your system for 'signal-safety' or similar. Here is a pointer on the web: https://man7.org/linux/man-pages/man7/signal-safety.7.html
pthread synchronization functions are not on the list.
However, One of the function listed there is sem_post: https://man7.org/linux/man-pages/man3/sem_post.3.html
sem_post() is async-signal-safe: it may be safely called within a
signal handler.
So, you can implement mutex-like synchronization using semaphores within the signal handler.

Catching signal from Python child process using GLib

I'm trying to control the way my cursor looks during certain points of my program execution. To be specific, I want it to be a "spinner" when a Python script is executing, and then a standard pointer when it's done executing. Right now, I have a leave-event-notify callback in Glade that changes the spinner when it leaves a certain area, but this is non-ideal since the user might not know to move the cursor and the cursor doesn't accurately represent the state of the program.
I have my Python program signalling SIGUSR1 at the end of execution. I am spawning the Python script from a C file using GLib's g_spawn_async_with_pipes. Is there any way to catch a signal from the child process that this creates? Thanks!
Pass the G_SPAWN_DO_NOT_REAP_CHILD flag to g_spawn_async_with_pipes() and then call g_child_watch_add() to get a notification when your Python subprocess exits. You don’t need to bother with SIGUSR1 if the process exits when it’s done.
It’s a bit hard to provide a more specific answer unless you post a minimal reproducible example of your code.

How to programmatically backtrace crash of forked child using C

Is there a possibility to backtrace a location where child process crashed in Linux using C/C++ code?
What I want to do is the following:
fork a new child process and retrieve it's PID
wait for forked child process to crash ... probably using signal handler for SIGCHLD, or using waitpid()/waitid()
retrieve stack trace of child at location where it crashed
This would make parent process act similar to debugger when attached proces crashes.
You can assume that child process is compiled with debug symbols and parent process has root permissions.
What is the simplest way to achieve such functionality?
It is much simpler in Linux to use the libSegFault library provided as part of the GNU C library. On my system, it is installed in /lib/x86_64-linux-gnu/libSegFault.so.
All you need to do is to set SEGFAULT_SIGNALS environment variable to all (so you can catch all crash causes the library supports), optionally SEGFAULT_OUTPUT_NAME to point to the file the stack trace is written to (default is to standard error), and LD_PRELOAD to point to the segfault library. As long as the process does not modify these environment variables, they apply to all child processes as well.
For example, if ./yourprog was the program that forks a child that crashes, and you want the stack trace to ./yourprog.stacktrace, run
SEGFAULT_SIGNALS=all \
SEGFAULT_OUTPUT_NAME=./yourprog.stacktrace \
LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so \
./yourprog
or all in one line without the backslashes (\).
The only downside is that each crash overwrites the existing file, so you'll only see the latest one. If you have /proc mounted, then the crash dump includes both a backtrace and the memory map of the process at the crash moment.
If you insist on doing it in your own C program, I recommend you first take a look at the libSegFault sources.
The point is, the stack trace must be dumped by the process itself; it is not accessible to the parent. To do that, you inject code into the child process using e.g. LD_PRELOAD environment variable (which is one of the dynamic linker control variables in Linux). (Note that the stack tracing etc. is done in a signal handler context, so only async-signal-safe functions should be used.)
For example, the parent process can create a pipe, and move its write end to a specific descriptor in the child process before executing the target process, with your helper preload library path in LD_PRELOAD.
The helper preload library interposes signal(), sigaction(), and possibly sigprocmask(), sigwait(), sigwaitinfo(), pthread_sigmask(), to ensure the helper librarys crash dump signal handlers are executed when such a signal is delivered (SIGSEGV, SIGBUS, SIGILL, possibly SIGTRAP). The signal handler does the stack dump (and prints /proc/PID/maps), then sets the signal disposition to default, and re-raises the signal (using raise()).
Essentially, it boils down to doing the same as above libSegFault, except with your own C code.
If you don't want to inject code to the child process, or managing the signal handlers is too complicated, you can use ptrace instead.
When the tracee is killed by a signal (other than SIGKILL), the thread receiving the signal is stopped first ("signal-delivery-stop"), so the tracer can examine its stack (and memory map of the tracee), before letting the child process continue/die.
In practice, ptracing is more invasive, as there are many events that cause the tracees threads to stop. It is also much more complicated for multithreaded processes than the LD_PRELOAD approach, because ptrace can control individual threads in the tracee; there are much more details to get right.

how to block a signal before shared library creates a thread?

I am dealing with application that requires certain signal to be blocked in every thread. Said app also dynamically links a library (libcpprest.so) which creates a thread pool during initialization. Naturally, because main executable had no chance to execute any code these threads have that signal unblocked -- which leads to mysterious crashes.
Is it possible to block a signal before dynamically linked library has a chance to create a thread?
Unacceptable solutions (that I am aware of):
link library statically and use init_priority to ensure signal is blocked asap
use "starter" utility that blocks signal and starts executable (which will inherit signals mask)
Doesn't seem to be possible -- shared library should block all signals in created threads if it really needs to create a thread so early.

Execute a function when a program exits normally or abnormally

I want to execute a housekeeping function when a C program exits. I know about atexit() which can help register a function for normal exit but will not work for signals like SIGINT or SIGQUIT. I don't want to register signal handlers for all such signals whose default behavior is to terminate the program. I just want to register a function which will get executed before a program terminates no matter what the reason is. How can I do this in C?
Can you run your c program as a child process ?
you could use any exec family function for that matter.
If your child process gets terminated normally or abnormally then there are much better options to query the exit status of the child from parent process.
According to that you should be able to invoke your function in parent.
Well I am not a C/C++ developer but have a look at this question that may help you. Shutdown Hook c++. There is a very fine way in Java though but in C I don't think there is a dedicated function to fullfill the purpose.
If you know already what type of signal you will be receiving you can write a signal handler in c.
for Linux check this answer: Ctrl + C interrupt event handling in Linux
some extra references:
https://www.gnu.org/software/libc/manual/html_node/Signal-Handling.html#:~:text=24%20Signal%20Handling,disconnection%20of%20a%20phone%20line.
For windows check the following link:
C++: Continue execution after SIGINT

Resources