pthread_cond_wait() and signal, the result depend on OS - c

I am a beginner of multi-threaded programming, and now I know that when a signal was sent while waiting with pthead_cond_wait(), the result depends on the OS.
Can somebody tell me how to know how the call was interrupted, and how to write portable code?
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
void
sigusr1_handler(int sig)
{
printf("signal called\n");
}
int
main()
{
int n;
pthread_mutex_t mut;
pthread_cond_t cond;
struct timespec ts;
signal(SIGUSR1, sigusr1_handler);
pthread_mutex_init(&mut, NULL);
pthread_cond_init(&cond, NULL);
pthread_mutex_lock(&mut);
printf("before cond_wait\n");
n = pthread_cond_wait(&cond, &mut);
printf("after pthread_cond_wait : %d\n", n);
perror("error pthread_cond_wait:");
pthread_mutex_unlock(&mut);
return 0;
}
MacOS X 10.11.4
cc -o condwait condwait.c -lpthread
Linux 2.6.32-642.3.1.el6.x86_64
gcc -o condwait condwait.c -lpthread
Solaris11 5.11 11.2
cc -D_POSIX_C_SOURCE -D_REENTRANT -mt -o condwait condwait.c -lpthread
MacOS X
$ ./condwait &
[1] xxxxx
$ kill -USR1 %1
signal called
after pthread_cond_wait : 0
error pthread_cond_wait:: Unknown error: 260
Solaris
$ ./condwait &
[1] xxxxx
$ kill -USR1 %1
signal called
after pthread_cond_wait : 0
error pthread_cond_wait : Error 0
Linux
$ ./condwait &
[1] xxxxx
$ kill -USR1 %1
signal called
$ jobs
[1]+ Running
When using Solaris native cond_wait(), it returns EINTR as documented.
Is there any idea how to know that pthread_cond_wait() was interrupted?

POSIX specifies that this function will never return EINTR. For portability to legacy OSes you can check for it anyway, it doesn't hurt
More importantly, you should be prepared for spurious wakeups. The function can return zero at any time for any reason wiith the condition not being met. The mutex will be locked. You have to check the condition and, if not met, go back to pthread_cond_wait.

I read the Linux pthread_cond_wait's man manual, it says:
If a signal is delivered to a thread waiting for a condition variable, upon return from the signal handler the thread resumes waiting for the condition variable as if it was not interrupted, or it shall return zero due to spurious wakeup.
I guess other OS's also have manuals to help you figure it out.

Thank you very much for everyone.
Now I know that with using signal to stop long waiting condition do not work.
pthread_cond_wait() resume waiting for the condition as if it was not interrupted, or it returns zero due to spurious wakeup.
Then I want to do that, I will need a second lock like
pthread_mutex_lock(&mut);
while(condition_is_false) {
n = pthread_cond_timedwait();
if (n == ETIMEDOUT) {
pthread_mutex_lock(&mut2);
if (condition2_is_true) {
pthread_mutex_unlock(&mut2);
pthread_mutex_unlock(&mut);
return STOPPED;
}
pthread_mutex_unlock(&mut2);
}
}
pthread_mutex_unlock(&mut);
return 0;
Regards,

Related

How to pause until signal and not have C print?

I'm guessing I need to call some function in my signal handler and I have no idea what it is
My program wants to sleep until it receives some kind of signal. So naturally I used pause(). Now it ran just fine when I sent my app SIGUSR1 however I get a print out of User defined signal 1 which is not what I want because I plan to send many signals and it will make the console unreadable. I tried handling the signal by writing signal(SIGUSR1, mySignalHandler); but now pause() no longer resumes after I receive the signal. Is there some kind of function I need to call from mySignalHandler?
The default behavior when a program receive a USR1 signal is to terminate (see https://www.man7.org/linux/man-pages/man7/signal.7.html, standard signal).
An empty signal handle will just do what you want: no message will be displayed.
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
static int s_got = 0;
void handler(int s)
{
++s_got;
}
int main(void)
{
signal(SIGUSR1, handler);
while(1) {
pause();
printf("resumed %d\n", s_got);
}
return 0;
}
:~/so/pause$ gcc -Wall main.c
:~/so/pause$ ./a.out &
[1] 2286
:~/so/pause$ pkill -USR1 a.out
resumed 1
:~/so/pause$ pkill -USR1 a.out
resumed 2
:~/so/pause$ pkill -USR1 a.out
resumed 3
:~/so/pause$ pkill -USR1 a.out
resumed 4
:~/so/pause$ pkill -USR1 a.out
resumed 5
:~/so/pause$

Why is my thread function running twice?

#include <stdio.h>
#include <sys/wait.h>
#include <pthread.h>
void* runfunc(void* arguments){
printf("in run thread\n");
return NULL;
}
int main(void)
{
pthread_t pthread_id;
pthread_create(&pthread_id, NULL, runfunc, NULL);
printf("after pthread creation\n");
return 0;
}
$ gcc -pthread intro.c
$ ./a.out
after pthread creation
in run thread
in run thread
$ ./a.out
after pthread creation
$
There are 4 types of outputs for this program on linux.
"after pthread creation" -> this output can be easily understood as before thread execution process completes and exits and deletes all threads.
"after pthread creation
in " -> this output can also be understood as while process was exiting thread executed a little bit to print in
"in running thread
after pthread creation" -> this output can also be easily understood
"after pthread creation
in running thread
in running thread" -> now i don't get why am i getting "in running thread" 2 times instead of once.
Linux implementation of threads is considered.

Why was default SIGPIPE handler changed?

I'm working on a test and i'm asked how to make a "read" sleep or a "write" stop a process"
For the latter I don't understand why my sigpipe is, indeed raised, but isn't stopping the process:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#define READING 0
#define WRITING 1
#define DESCRIPTOR_COUNT 2
void signal_handler(int signal){
printf("sigpipe received\n");
}
int main(void)
{
int tube[DESCRIPTOR_COUNT];
pipe(tube);
// signal(SIGPIPE, signal_handler);
close(tube[READING]);
if(write(tube[WRITING], "message", 8)<0)
if(errno==EPIPE)
printf("EPIPE returned\n");
printf("123");
return EXIT_SUCCESS;
}
Without signal() (quoted)
With signal() (unquoted)
SIGPIPE is indeed received, but in the case I don't handle it the process should stop, but since I can write "123" this means the process wasn't stopped.
Why?
Also I'm on Fedora 28, i'm using codeblocks 17.12.
Was SIGPIPE ignored...? Reason?
SOLUTION ?
struct sigaction action;
action.sa_handler = SIG_DFL;
sigaction(SIGPIPE, &action, 0);
Replacing signal() with this will have the default behaviour as expected!
EDIT I've now changed the title from "SIGPIPE doesn't stop process" to "Why was default SIGPIPE handler changed?"
======================================================
Answer
After talking with the guys from codeblocks, codeblocks uses wxWidgets, and on linux (fedora 28 here) wxWidgets uses gtk library, as explained by Mark Plotnick in the comments, gtk changes the signal handler for SIGPIPE, since codeblocks runs codes using a fork or an exec, the code run through codeblocks is influenced by gtk library.
The behaviour you are reporting is consistent with the Code::Blocks IDE setting, implicitly or explicitly, the SIGPIPE behaviour to SIG_IGN. This is readily inherited. It isn't what I'd expect — I'd expect your program to be launched with SIGPIPE (and, indeed, all other signals) set to SIG_DFL, the default signal behaviour. If this turns out to be the problem, you have the basis for a bug report to the developers of Code::Blocks. If it turns out not to be the problem, then we've got some hard thinking ahead to work out what actually is happening*.
You could demonstrate whether this is what's happening with Code::Blocks by paying attention to the return value from signal(), or by using sigaction() to interrogate the signal handling mode without modifying it.
For example:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#define READING 0
#define WRITING 1
#define DESCRIPTOR_COUNT 2
static void signal_handler(int signum)
{
// Lazy; normally, I'd format the signal number into the string, carefully
(void)signum;
write(STDOUT_FILENO, "sigpipe received\n", sizeof("sigpipe received\n")-1);
}
int main(void)
{
void (*handler)(int) = signal(SIGPIPE, signal_handler);
if (handler == SIG_DFL)
printf("old handler was SIG_DFL\n");
else if (handler == SIG_IGN)
{
printf("old handler was SIG_IGN\n");
(void)signal(SIGPIPE, SIG_IGN);
}
else
{
// Standard C does not allow a cast from function pointer to object pointer
//printf("there was a non-standard handler installed (%p)\n", (void *)handler);
printf("there was a non-standard handler installed\n");
}
int tube[DESCRIPTOR_COUNT];
pipe(tube);
close(tube[READING]);
if (write(tube[WRITING], "message", 8) < 0)
{
if (errno == EPIPE)
printf("EPIPE returned\n");
else
printf("errno = %d\n", errno);
}
printf("123\n");
return EXIT_SUCCESS;
}
Note that the standard idiom for setting a signal handler using signal() in a program was:
if (signal(signum, SIG_IGN) != SIG_IGN)
signal(signum, signal_handler);
This means that if a program was protected from signals, it stays protected. If it was handling signals (by default, or perhaps explicitly by a prior call to signal()), then you install your own signal handler. Equivalent code using sigaction() would be:
struct sigaction sa;
if (sigaction(signum, 0, &sa) == 0 && sa.sa_handler != SIG_IGN)
{
sa.sa_handler = signal_handler;
sa.sa_flag &= ~SA_SIGINFO;
sigaction(signum, sa, 0);
}
(One advantage of this: the structure is initialized by the call to sigaction(), so there's no need to fiddle with the masks. The tweak to the flags ensures that the basic handler, not the extended handler, is used.)
When I compile the source code (pipe13.c) into program pipe13 and run it, I get:
$ make pipe13
gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes pipe13.c -o pipe13
$ pipe13
old handler was SIG_DFL
sigpipe received
EPIPE returned
123
$ (trap '' 13; pipe13)
old handler was SIG_IGN
EPIPE returned
123
$
This variant uses sigaction() to interrogate the signal handling:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#define READING 0
#define WRITING 1
#define DESCRIPTOR_COUNT 2
int main(void)
{
struct sigaction sa;
if (sigaction(SIGPIPE, 0, &sa) != 0)
fprintf(stderr, "siagaction() failed\n");
else if (sa.sa_handler == SIG_DFL)
printf("old handler was SIG_DFL\n");
else if (sa.sa_handler == SIG_IGN)
printf("old handler was SIG_IGN\n");
else
printf("there was a non-standard handler installed\n");
int tube[DESCRIPTOR_COUNT];
pipe(tube);
close(tube[READING]);
if (write(tube[WRITING], "message", 8) < 0)
{
if (errno == EPIPE)
printf("EPIPE returned\n");
else
printf("errno = %d\n", errno);
}
printf("123\n");
return EXIT_SUCCESS;
}
When run (program pipe83), I get:
$ pipe83
old handler was SIG_DFL
$ echo $?
141
$ (trap '' 13; pipe83)
old handler was SIG_IGN
EPIPE returned
123
$
Note that with the default signal handling, the program terminates before printing 123. POSIX shells encode 'child died from signal N' by reporting the exit status as 128 + N; SIGPIPE is 13, so 141 indicates that the shell died from a SIGPIPE signal. (Yes, modern youngsters would probably write (trap '' PIPE; pipe83) and it works — such niceties weren't available when I learned shell programming.)
It would not be all that hard to generalize the code to test whether Code::Blocks sets any other signals to other than the default handling. It can be a little fiddly, though, if you want to adapt to which signals are available on a machine.
* In chat, we established that the program is run in a VMware image running Fedora 28, hosted on a Windows 10 machine. Because of this, there are enough possible places for there to be trouble that it is not clear that the problem is necessarily in Code::Blocks — it is simply not clear where the problem originates. However, the problem does indeed seem to be that the test program is started with SIGPIPE handling set to SIG_IGN instead of SIG_DFL when it is run from Code::Blocks.
Code::Blocks is not a compiler, just an IDE. It (probably) runs the GCC compiler. And the GCC compiler don't matter much for signal handling. Read signal(7) and signal-safety(7) for more (calling printf inside a signal handler is forbidden because printf is not async-signal-safe so your printf("sigpipe received\n"); inside a signal handler is undefined behavior). Signal handling is done mostly by the Linux kernel (see its source code on kernel.org) with a small bit of it handled by your C standard library, probably GNU glibc.
It seems codeblocks changes the default signal handler for SIGPIPE
This is very unlikely (and almost certainly false). You could use strace(1) on your program to understand what system calls it is doing.
printf("123");
You forgot a \n. Remember that stdout is usually line-buffered. Or you should call fflush(3).
When you run a program from inside Code::Blocks it could run without a terminal. I strongly recommend running your program inside a terminal emulator (see tty(4) and pty(7)). The C standard library is permitted to use something like isatty(3) to behave differently when stdout is or is not a tty (in particular, buffering is done differently, see setvbuf(3)). Read the tty demystified and termios(3).
You could also try to run your program by redirecting its stdin, stdout, stderr to a file or a pipe (perhaps using |& cat or |& less with bash or zsh), or anything which is not a tty.
BTW, Code::Blocks is free software. You can study its source code to understand what it is doing.
Consider also using stdbuf(1) to run your program with different buffering operations.

Buffering `printf` outputs between different threads in Linux

Here is my code:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
pthread_t ntid;void
printids(const char *s) {
printf("%s \n", s);
}
void *
thr_fn(void *arg) {
printids("new thread: ");
return((void *)0);
}
int
main(void) {
pthread_create(&ntid, NULL, thr_fn, NULL);
printids("main thread:");
}
I'm running it on Red Hat Enterprise Linux Workstation release 6.5 .
Here is my compiling command
gcc -ansi -g -std=c99 -Wall -DLINUX -D_GNU_SOURCE threadid.c -o threadid -pthread -lrt -lbsd
Here is the output:
main thread:
new thread:
new thread:
Why "new thread" has been printed twice?
I doubt this may related to buffering mechanism in Linux. But after I added fflush(stdout) and fsync(1) in the end of each function. The output is almost the same.
If you run the program several times. The output differs:
main thread:
new thread:
or
main thread:
new thread:
new thread:
Or
main thread:
Most libc libraries do buffer the output as you mentioned. And at the end of the program (when the main thread exits), they flush all the buffers and exit.
There is a slight possibility that your new thread has flushed the output but before it could update the state of the buffer, the main program exited and the cleanup code flushed the same buffer again. Since these buffers are local to the thread I am sure they won't have concurrency mechanism. But because of this rare case it might get messed up.
You can try
err = pthread_create(&ntid, NULL, thr_fn, NULL);
printids("main thread:");
pthread_join(ntid, NULL);
At the end of the main function and check if the problem is solved.
This will cause your main function to wait till the new thread is finished (including the flushing operation it does).
Double output is possible on glibc-based linux systems due to a nasty bug in glibc: if the FILE lock is already held at the time exit tries to flush, the lock is simply ignored and the buffer access is performed with no synchronization. This would be a great test case to report to glibc to pressure them to fix it, if you can reproduce it reliably.

GDB breakpoint in routine of a simple Pthread?

I have the following code (source):
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid) {
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld\n", tid);
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t threads[NUM_THREADS];
int rc;
long t;
for (t=0; t<NUM_THREADS; t++) {
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
// wait for all threads to die
pthread_exit(NULL);
}
I compile with gcc -g main.c -o main -lpthread. I am using GDB for debugging. What I want is to place a breakpoint at the second line of PrintHello, i.e. at tid = (long)threadid, and have the execution stop there (whatever the thread) and let me do stuff like look at the value of variable threadid.
I want to achieve this in Emacs' GDB implementation - which we may assume for the purposes of this question as simply GDB (don't worry that it's run inside Emacs). So far I can place the breakpoint at the desired line, and sometimes the little arrow showing the current line where the program is at does indeed stop at this line:
However when I type into the GDB prompt print threadid I get back No symbol "threadid" in current context. and the arrow jumps immediately to some breakpoint that I set in main():
My guess is that this occurs because the "pausing" of program execution happens for the main thread, which is not the thread running PrintHello. PrintHello is run by thread t - since this is not the thread paused by GDB, it prints the hello world message and exists immediately. By the time I get around to typing print threadid, this thread is already dead and the program is back in main()... hence the effect.
I tried to resolve this by typing something like break <LineNumber> thread <ThreadID> but this is no good since in this program the created threads last for a split second. So I am never actually at a point where info thread shows anything except the main thread. It's simply not humanly possible to "catch" the program at a point where there is the main thread and a newly created thread running PrintHello - since this situation lasts for I guess a few microseconds.
Please help me to achieve this simple debug objective of halting execution of whatever thread is executing PrintHello at the line tid = (long)threadid;.
Solved it, there wasn't much a problem after all. Here are instructions, if anyone has a similar issue:
Compile with gcc -ggdb main.c -o main -lpthread (yes, that's -ggdb and not -g, it appears to make a difference)
Run the debugger with gdb main or, in Emacs, with M-x gdb (and the command gdb -i=mi main)
Hugely important here: Emacs has by default the variable gdb-non-stop-setting set to t, which means it tries to run GDB in non-stop mode. According to docs, this is NOT what I want - I want all-stop mode. Thus, either do a set-variable or put (setq gdb-non-stop-setting nil) in your init file (e.g. ~/.emacs.d/init.el). Only once this is done should you launch M-x gdb from inside Emacs...
(gdb) b 9 to set the breakpoint to line 9
(gdb) r to run the program. Execution will stop when one of the threads reaches line 9, i.e. tid = (long)threadid;. All other threads will also stop! Perfect!
(gdb) c to continue. Execution will stop when another thread reaches line 9. Great!
Continue doing whatever, we have the desired behavior now :)

Resources