Process terminated when signaling a pthread waiting on "join" - c

I'm trying to implement a signal handler.
each pthread is created joinable, and is blocked upon all signals using sigprocmask.
The problem occurs when I send the thread a signal from another thread, using
pthread_kill(_threads[threadIndex], SIGHALT);
If the called pthread is waiting on pthread_join at the time the signal is sent, the whole proccess is terminated immidiately. However, if the thread is not waiting on join, it ignores the signal as expected. Any idea why does it happen and how to change it?
Thank you!

Regarding the use of sigprocmask() in a mutithreaded environment please see this excerpt from the methods's man page:
The use of sigprocmask() is unspecified in a multithreaded process;
see pthread_sigmask(3).
I'm a bit unsure about SIGHALT, but assuming it's a synonym to SIGSTOP the following from pthread_kill()'s man page might be of interest:
Signal dispositions are process-wide: if a signal handler is
installed, the handler will be invoked in the thread thread, but if
the disposition of the signal is "stop", "continue", or "terminate",
this action will affect the whole process.

Related

Signal that can be used just by my application

I am programming a tree of processes in Linux and I wonder if there is any signal that can be used just to send from A process to B process without affecting B process.
For example, assume B_pid is the process B's ID, if process A calls kill(B_pid, SIGSTOP); then A will pause B. What I am looking for is a signal, let's say SIGNOTHING, that when A calls kill(B_pid, SIGNOTHING), then it just simply sends a message to B rather than doing something to both B and the system.
SIGUSR1 and SIGUSR2 are designed for that purpose.
If you invoke the following command on your shell:
kill -l
you get a full list of signals available for your system.
Most of the signals can be used to simply "receive" them on the target side. BUT: Most signals are also used by the system itself to tell the application that something special happened, like SIGSEGV. So it makes no sense to use signals, which have a fixed meaning as they are used to communicate from kernel/OS to the application.
For user signals, you have two signals reserved, which can be used for everything you like: SIGUSR1 and SIGUSR2.
Not all Unix systems have these signals! So first take a look which signals can be used on your current system!
Additional hint:
Check you signal handlers and the context on which they are running. On some implementations it is not allowed to call non-reentrant functions from the context of the handler. So it is maybe more useful to communicate via a pipe or any other IPC method.
There are signals that are meant for use for user programs. From man signal:
The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.
SIGSTOP will always stop the program and SIGKILL will always terminate the program.
There are two user-defined signals commonly used for signal communication between processes:
SIGUSR1 ... User-defined signal 1
SIGUSR2 ... User-defined signal 2
And there is also a whole range of real-time signals for use as user-defined signals between SIGRTMIN and SIGRTMAX, that have to be at least 8 signals (ie. SIGRTMAX - SIGRTMIN >= 8) and linux supports 33 signals. These are all for use for user-application to do anything it desires.
Basically each signal in Linux has a action associated with it.
Man page of signal:
Signal dispositions
Each signal has a current disposition, which determines how the
process behaves when it is delivered the signal.
The entries in the "Action" column of the table below specify the
default disposition for each signal, as follows:
Term Default action is to terminate the process.
Ign Default action is to ignore the signal.
Core Default action is to terminate the process and dump core (see
core(5)).
Stop Default action is to stop the process.
Cont Default action is to continue the process if it is currently
stopped.
SIGSTOP
SIGSTOP P1990 Stop Stop process
A process can change the disposition of a signal using sigaction(2)
or signal(2). (The latter is less portable when establishing a
signal handler; see signal(2) for details.) Using these system
calls, a process can elect one of the following behaviors to occur on
delivery of the signal: perform the default action; ignore the
signal; or catch the signal with a signal handler, a programmer-
defined function that is automatically invoked when the signal is
delivered.
You can define your own signal handler and define the behavior of your process.
Note: SIGKILL and SIGSTOP cannot be caught

How to wait a signal in a thread?

I'm sending a signal from a module in the kernel space to a process. This process has one thread waiting for the signal.
I read the signal manual and it says:
The signal disposition is a per-process attribute: in a multithreaded application, including the disposition of a signal is the same for all threads.
Thus, and according to the manual pthread_sigmask:
http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html
I'm trying to block the signal in the main function of the application by calling:
siginfo_t infoh1;
sigset_t waith1;
sigemptyset(&waith1);
sigaddset(&waith1, SIG_HILO1);
pthread_sigmask( SIG_BLOCK, &waith1, NULL );
Note that the thread is waiting for it in its execution function.
result = sigwaitinfo (&waith1, &infoh1);
The signal is sent, but the thread never receives it (it hangs waiting).
What am I doing wrong? I tested with different codes from different websites without success.
I use signals a lot in my *nix code and I don't think this is a good approach.
I recommend that all threads are set to ignore signals. The main process handles the signal while the thread sits on a mutex/condition. On signal the main process sets a global static flag with the signal type and then notifies the thread which duly checks the flag to see which signal was caught.
It's a safe and easy solution.

handling of 2 signals at aproximately the same time

In Linux 2.6, I would like my process to catch both SIGHUP and SIGTERM in order to exit orderly.
When the node shuts down, logs show that it will handle either SIGHUP (the parent process receives SIGTERM) or SIGTERM first.
My question is: is there a possibility that the handlers for these signals are called concurrently? or the kernel triggers one after the other?
Depending on your code architecture you could enforce synchronous reading of signals preventing any concurrency issues. You could use signalfd and then read from that fd whenever you want to check on any outstanding signals. If you need them to behave in their asynchronous default with a signal handler I think you have to be prepared for your signal handler to be potentially interrupted.
man signalfd
In Asynchronous signals to a process, the Linux kernel send signals with a system call to target process structure and when context of the process is switched to RUN state, signals are handled by root thread and block signals on all other threads. Since the stack space is different for each thread each signal can be handled at a time(Correct if am wrong).

Can a detached pthread die?

Can a pthread, that is detached, die? Can the thread be killed by the OS without stopping the main process?
If you program a detached thread to die after doing its work then it will die. After concluding its work the function can simply end or call pthread_exit.
You can kill a detached thread from another thread by sending a signal with pthread_kill or using a global flag or a form of IPC such as a pipe or message queue. Note the word "killed" is ambiguous between its multiple meanings in both English and programming. The thread needs to be programed to react to whatever notification mechanism is used. For instance a signal handler should be installed for the thread and a non-process-wide signal such as SIGUSR1 sent with pthread_kill or pthread_sigqueue. Lastly pthreads has a cancellation mechanism you can employ using pthread_cancel and related calls. In all these scenarios the point is that the thread must be programmed to handle a request to die gracefully but "detached" does not mean "inaccessible".
If the disposition of a signal is stop, continue or terminate it will affect the process as a whole not a single thread.

Kill Thread in Pthread Library

I use pthread_create(&thread1, &attrs, //... , //...); and need if some condition occured need to kill this thread how to kill this ?
First store the thread id
pthread_create(&thr, ...)
then later call
pthread_cancel(thr)
However, this not a recommended programming practice! It's better to use an inter-thread communication mechanism like semaphores or messages to communicate to the thread that it should stop execution.
Note that pthread_kill(...) does not actually terminate the receiving thread, but instead delivers a signal to it, and it depends on the signal and signal handlers what happens.
There are two approaches to this problem.
Use a signal: The thread installs a signal handler using sigaction() which sets a flag, and the thread periodically checks the flag to see whether it must terminate. When the thread must terminate, issue the signal to it using pthread_kill() and wait for its termination with pthread_join(). This approach requires pre-synchronization between the parent thread and the child thread, to guarantee that the child thread has already installed the signal handler before it is able to handle the termination signal;
Use a cancellation point: The thread terminates whenever a cancellation function is executed. When the thread must terminate, execute pthread_cancel() and wait for its termination with pthread_join(). This approach requires detailed usage of pthread_cleanup_push() and pthread_cleanup_pop() to avoid resource leakage. These last two calls might mess with the lexical scope of the code (since they may be macros yielding { and } tokens) and are very difficult to maintain properly.
(Note that if you have already detached the thread using pthread_detach(), you cannot join it again using pthread_join().)
Both approaches can be very tricky, but either might be specially useful in a given situation.
I agree with Antti, better practice would be to implement some checkpoint(s) where the thread checks if it should terminate. These checkpoints can be implemented in a number of ways e.g.: a shared variable with lock or an event that the thread checks if it is set (the thread can opt to wait zero time).
Take a look at the pthread_kill() function.
pthread_exit(0)
This will kill the thread.

Resources