Hi fellow programmers,
I wanted to write a simple multi-threaded program in C with pthread, but somehow the pthread_join seems to hang.
It seems happens not always, sometimes everything is running fine, next time it't hanging againg, usually on the first thread.
I already minimized the code to the bare minimum, so that i can exclude other problems. In the full code the threads did some computations, of course. But the problems still persists even with this very reduced code. And on more than one machine, with different OS'es.
strace shows me that the hanging has something to do with a FUTEX_WAIT, the full last lines:
write(1, "Joining Thread 0...\n", 20Joining Thread 0...
) = 20
futex(0x7fff61718a20, FUTEX_WAIT, 1634835878, NULL
I tried to debug it with gdb, but my poor debugging stills are very limited, especially with multi-threaded programs.
I also tried to compile it using different C-standards (C99 and Ansi) and both pthread parameters (-lpthread, -pthread), but the problem still persists.
The (reduced) code monte2.c:
#include <stdio.h>
#include <pthread.h>
void *monte(struct MonteArgs *args) {
pthread_exit(NULL);
}
int main(int argc, char **argv) {
int numThreads, numSamples;
int i;
if (argc != 3) {
printf("Usage: monte threads samples\n");
exit(1);
}
numThreads = atoi(argv[1]);
pthread_t threads[numThreads];
numSamples = atoi(argv[2]);
for (i=0; i<numThreads; i++) {
if (pthread_create(&threads[i], NULL, monte, NULL)) {
printf("Error Creating Thread %d!\n", i);
return 1;
}
}
for (i=0; i<numThreads; i++){
printf("Joining Thread %d...\n", i);
pthread_join(&threads[i], NULL);
}
printf("End!\n");
fflush(stdout);
return(0);
}
I compile with
gcc monte2.c -lpthread -o monte
and run with
./monte2 3 100
where the first argument is the number of threads, and the second is actually not needed for the reduced code.
It's been a while since I've done multi-threaded C, but you shouldn't ignore compiler warnings :-). Compile with -Wall.
You should be seeing a warning like this:
note: expected 'pthread_t' but argument is of type 'pthread_t *'
int WINPTHREAD_API pthread_join(pthread_t t, void **res);
You are passing a pthread_t* when you should be passing pthread_t.
Refer to the pthread_join docs: http://man7.org/linux/man-pages/man3/pthread_join.3.html
Related
I am trying to create a semaphore and practicing by using this simple program, though I am getting a bunch of deprecated warnings when compiling on macos. I have been looking and having trouble finding a solution to get the semaphore to work for macos.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#define THREAD_NUM 4
sem_t semaphore;
void* routine(void* args) {
sem_wait(&semaphore);
sleep(1);
printf("Hello from thread %d\n", *(int*)args);
sem_post(&semaphore);
free(args);
}
int main(int argc, char *argv[]) {
pthread_t th[THREAD_NUM];
sem_init(&semaphore, 0, 1);
int i;
for (i = 0; i < THREAD_NUM; i++) {
int* a = malloc(sizeof(int));
*a = i;
if (pthread_create(&th[i], NULL, &routine, a) != 0) {
perror("Failed to create thread");
}
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
sem_destroy(&semaphore);
return 0;
}
I am expecting the threads to be created for the routine function where 4 threads exist for 4 void* routine(). It should
printf("Hello from thread") every second starting from thread 0 and going to 3. What is actually happening is all the printf statements get outputed to the console after 1 second at the same time.
Output:
Hello from thread 0
Hello from thread 1
Hello from thread 2
Hello from thread 3
Compiler information:
test.c:18:1: warning: non-void function does not return a value [-Wreturn-type]
}
^
test.c:22:5: warning: 'sem_init' is deprecated [-Wdeprecated-declarations]
sem_init(&semaphore, 0, 4);
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/semaphore.h:55:42: note: 'sem_init' has been explicitly marked deprecated here
int sem_init(sem_t *, int, unsigned int) __deprecated;
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:204:40: note: expanded from macro '__deprecated'
#define __deprecated __attribute__((__deprecated__))
^
test.c:37:5: warning: 'sem_destroy' is deprecated [-Wdeprecated-declarations]
sem_destroy(&semaphore);
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/semaphore.h:53:26: note: 'sem_destroy' has been explicitly marked deprecated here
int sem_destroy(sem_t *) __deprecated;
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:204:40: note: expanded from macro '__deprecated'
#define __deprecated __attribute__((__deprecated__))
^
3 warnings generated.
I am expecting the threads to be created for the routine function where 4 threads exist for 4 void* routine(). It should printf("Hello from thread") every second starting from thread 0 and going to 3.
I would expect that, too, on any machine that provides POSIX-conforming pthreads, POSIX semaphores, and sleep(). Especially if you resolve the first of the warnings -- for example, by adding return NULL; at the end of function routine().
My expectation is fulfilled on my Linux test machine. However, there are comments around various parts of the web suggesting that MacOS does not support unnamed semaphores, which is what you are trying to use by calling sem_init(). As I understand it, this is the significance of the deprecation warnings you report -- the functions are there, but (I guess) they don't actually work.
If indeed MacOS's sem_init() is non-functional, then calls to it should return an error code. You don't know whether that's happening, because you don't check for it. Always check your functions' error indicators if in fact you care whether they succeeded (and here, you certainly do).
One possible workaround that does not require abandoning POSIX interfaces would be to switch to named semaphores instead of unnamed ones. That would involve using sem_open() and sem_close() instead of sem_init() and sem_destroy().
What is actually happening is all the printf statements get outputed to the console after 1 second at the same time.
That certainly sounds like the semaphore is not working. Your threads are working, because you get the output at all, and they are running in parallel, because their sleep()s all expire at about the same time. Again, check the error indicators of your function calls (their return values for all library functions in the example code), as this will often clue you in when something does not work as you expect, whether because of something wrong with your code or because erroneous data or runtime environment.
There is an interesting issue.
If we don't add the return value in an integer function that maybe the program will hang up or segment fault when running it in embedded devices which based arm gcc8.
But there are different behavior in different compiler version on this issue.
We know the compiler will report a warning that we have not the return value in an integer function.
But it looks like that the cross compiler(8.2.0) don't know the next step after running out the integer function.
GCC-4.5.2
GCC-6.3.0
arm-linux-gnueabi(4.5.2)
arm-ccp-linux-gnueabi(8.2.0)
program running status
Well
Well
Well
Hang up or segment fault
GCC-4.5.2 ----------work well
GCC-6.3.0 ----------work well
arm-linux-gnueabi(4.5.2)----------work well
arm-ccp-linux-gnueabi(8.2.0)----------hang up or segment fault in embedded device
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
int a_function_die(int aa)
{
// return 0;
}
void *poll_thread(void *arg)
{
printf("before call a_function_die\n");
a_function_die(123);
printf("after call a_function_die\n");
while(1) {
printf("I am aliave\n");
sleep(1);
}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t pid;
pthread_create(&pid, NULL, poll_thread, NULL);
pause();
return 0;
}
I'm fairly new to threads in C. For this program I need to declare a thread which I pass in a for loop thats meant to print out the printfs from the thread.
I can't seem to get it to print in correct order. Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 16
void *thread(void *thread_id) {
int id = *((int *) thread_id);
printf("Hello from thread %d\n", id);
return NULL;
}
int main() {
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
int code = pthread_create(&threads[i], NULL, thread, &i);
if (code != 0) {
fprintf(stderr, "pthread_create failed!\n");
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
//gcc -o main main.c -lpthread
That's the classic example of understanding multi-threading.
The threads are running concurrently, scheduled by OS scheduler.
There is no such thing as "correct order" when we are talking about running in parallel.
Also, there is such thing as buffers flushing for stdout output. Means, when you "printf" something, it is not promised it will happen immediately, but after reaching some buffer limit/timeout.
Also, if you want to do the work in the "correct order", means wait until the first thread finishes it's work before staring next one, consider using "join":
http://man7.org/linux/man-pages/man3/pthread_join.3.html
UPD:
passing pointer to thread_id is also incorrect in this case, as a thread may print id that doesn't belong to him (thanks Kevin)
This program should be a trivial attempt to run two concurrent threads which both need to write on the same screen.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <ncurses.h>
void *function1(void *arg1);
void *function2(void *arg2);
int main(int argc, char *argv[])
{
printf("hello");
initscr();
printw("screen on\n");
pthread_t function1t;
pthread_t function2t;
if( pthread_create( &function1t, NULL, function1, NULL) < 0)
{
printw("could not create thread 1");
return 1;
}
if( pthread_create( &function2t, NULL, function2, NULL) < 0)
{
printw("could not create thread 2");
return 1;
}
endwin();
return 0;
}
void *function1(void *arg1)
{
printw("Thread 1\n");
while(1);
}
void *function2(void *arg2)
{
printw("Thread 2\n");
while(1);
}
But it doesn't even print hello in the beginning. What's wrong? How can a unique screen be handled in such a program, with two threads?
Update: putting a refresh(); after each printw produces the following output
screen on
Thread 1
Thread 2
$
Where $ is the prompt. So, the program prints the string, but it puts (apparently) randomly some unexpected newlines and it ends. It shouldn’t, due to the while(1) instructions in both the threads!
curses/ncurses in the normal configuration does not support threads, and the recommendation for that has always been to run curses in a single thread. Since ncurses 5.7, there has been rudimentary support for threaded applications if the library is configured (compile-time) to use mutexes and additional entrypoints.
Regarding mutexes, almost any tutorial on POSIX threads covers that. Here is an example: POSIX Threads Programming
It is not printing the hello string but it's quickly cleared with the instruction initscr():
The initscr code determines the terminal type and initializes all
curses data structures. initscr also causes the first call to refresh
to clear the screen. If errors occur, initscr writes an appropriate
error message to standard error and exits; otherwise, a pointer is
returned to stdscr.
printw is printing as expected because you are not refreshing. You should use refresh() after each printw:
printw("screen on\n");
refresh();
One final question for the evening. I have a homework question that I cannot seem to solve, and after spending the better part of the night on it, I'll ask it here.
The problem is a program that is to calculate the Fibonacci sequence given an integer input at the command line (./foo.out 15, for example, and it will calculate the first 15 Fibonacci numbers). The additional parameters are as follows:
1.) It must use two POSIX threads, a parent thread and a child thread.
2.) It must share data (an array) between them.
Currently, the function is breaking when program control passes back to the parent thread. All I am getting is a completely non-descriptive segfault. As can be seen below, I have it outputting at every possible change in control.
Code:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
void *fibonacci(void *param, int numbers[]);
void *runner(void *param);
int main(int argc, char *argv[])
{
pthread_t tid;
pthread_attr_t attr;
if ( argc != 2)
{
fprintf(stderr, "Usage: 426.out <integer value> \n");
return -1;
}
if (atoi(argv[1]) < 0)
{
fprintf(stderr, "Argument must be non-negative\n");
return -2;
}
pthread_attr_init(&attr);
pthread_create(&tid, &attr, runner, argv[1]);
pthread_join(tid,NULL);
return 0;
}
void *fibonacci(void *param, int numbers[])
{
int it, IT_MAX;
printf("Entering Child Thread:\n");
IT_MAX = atoi(param);
numbers[0] = 0;
numbers[1] = 1;
for (it = 2; it < IT_MAX; ++it)
{
numbers[it] = (numbers[it - 1] + numbers[it - 2]);
}
for (it = 0; it < IT_MAX; ++it)
{
printf("%d\n", numbers[it]);
}
printf("Exiting Child Function.\n");
}
void *runner(void *param)
{
int it, IT_MAX;
int numbers[IT_MAX];
pthread_t tid;
pthread_attr_t attr;
printf("Entering Parent Thread:\n");
pthread_attr_init(&attr);
pthread_create(&tid, &attr, fibonacci(param, numbers), NULL);
pthread_join(tid, NULL);
IT_MAX = atoi(param);
for (it = 0; it < IT_MAX; it++)
{
printf("%d\n", numbers[it]); // I suspect the program breaks here
// It produces a segfault rather than this
}
printf("Leaving Parent Thread\n");
}
The question I have, if it is not clear from above, is what am I doing wrong. I am using gcc, and have been using the -Wall -Werror and -lpthread. -Werror keeps throwing "Control Structure going to end of non-void function", but nothing has anything to say about what can be causing the segfault. As before, I looked for the last hour for a question or article that addresses this, so if this is a dupe, please point me to the question or article in which it is addressed. Thanks to anyone in advance for their help.
One of your problems is in this line:
pthread_create(&tid, &attr, fibonacci(param, numbers), NULL);
Instead of starting a thread with the fibonacci() function, this calls the fibbonacci() function in the current thread and passes the result to pthread_create() as the thread start function. fibonacci() doesn't return a function pointer, so this new thread will crash the program.
You need to just pass fibonacci as the third parameter.
Futhermore, fibonacci() must be declared as void *fibonacci(void *) in order to be used as a thread start function. If you want to pass two parameters, you'll need to place them into a struct and pass a pointer to that.
This pair of lines is also problematic:
int it, IT_MAX;
int numbers[IT_MAX];
IT_MAX is an uninitialised variable, and you use it here to define the size of the numbers[] array. That could also be leading to your crash.
This line
pthread_create(&tid, &attr, fibonacci(param, numbers), NULL);
does not pass the address of fibonacci() to pthread_create() but calls fibonacci(param, numbers)and passes the result returned to pthread_create() as 3rd argument.