Reputation: 5924
I am new to threads.
I have written a sample program to create a thread.
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
#include<string.h>
#include<pthread.h>
void * func(void * temp)
{
printf("inside function\n");
return NULL;
}
int main()
{
pthread_t pt1;
printf("creating thread\n");
pthread_create(&pt1,NULL,&func,NULL);
printf("inside main created thread\n");
return 0;
}
After compilation the answer is found to be :
creating thread
inside main created thread
inside function
inside function
I understand that answer may vary as return 0;
may be called before the printf
in func is executed.
But how come in the solution, inside function
is printed two times?
On compiling With gcc -o temp thread1.c -lpthread
on first run:
creating thread
inside main created thread
on second run:
creating thread
inside main created thread
inside function
inside function
On compiling with gcc -pthread -o temp thread1.c
On first run:
creating thread
inside main created thread
inside function
inside function
I have observed this behavior on
gcc version: 4.4.3 (Ubuntu 4.4.3-4ubuntu5)
Kernel release:2.6.32-24-generic
glib version:2.11.1
Upvotes: 8
Views: 985
Reputation: 415
I can't comment, but there are several duplicate questions with more informative answers. A glibc bug is likely the cause of the unexpected behavior, and as noted in other answers, pthread_exit
and pthread_join
are suggested workarounds.
Upvotes: 0
Reputation: 440
For starters, as far as I can remember, compiling with "-pthread" is equivalent to compiling with "-D_REENTRANT -lpthread", so that's the only difference there. Note that printf and the like are not reentrant because they operate on a global buffer.
Having said that, I was unfortunately not able to recreate the interesting part of your problem (your printf inside the thread target function seeming to have been called twice). Each method of compilation (-lpthread and -pthread) gives me the same result: I get the prints from inside main, but none of the printing from within the thread target (as you mentioned you saw on your first run). I think this is just a timing issue, with the thread target not "getting around to" printing before main exits. In fact, just sleeping for 1/100 second before returning from main gets me the thread target function's printing. Give it a try and let us know what you see:
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
#include<string.h>
#include<pthread.h>
#include <unistd.h>
void * func(void * temp)
{
printf("inside function\n");
return NULL;
}
int main()
{
pthread_t pt1;
printf("creating thread\n");
pthread_create(&pt1,NULL,&func,NULL);
printf("inside main created thread\n");
/* ZzzzzZZZ... */
usleep(10000);
return 0;
}
I played around with the delay time, and even with 1/1000000 second: usleep(1); I still get all of my expected printfs. As the sleep delay decreases, the printing is more likely to occur out of order, which I would expect to see.
So regarding the multiple prints: As many before me pointed out, printf and the like operate on global structures, and are not reentrant. I'd be interested to see your output if you flushed stdout after your printf, all being protected by a mutex:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void * func(void * temp)
{
pthread_mutex_lock(&mutex);
printf("inside function\n");
fflush(stdout);
pthread_mutex_unlock(&mutex);
return NULL;
}
int main()
{
pthread_t pt1;
pthread_mutex_lock(&mutex);
printf("creating thread\n");
fflush(stdout);
pthread_mutex_unlock(&mutex);
pthread_create(&pt1,NULL,&func,NULL);
pthread_mutex_lock(&mutex);
printf("inside main created thread\n");
fflush(stdout);
pthread_mutex_unlock(&mutex);
usleep(10000);
return 0;
}
EDIT
I'm sorry, I wasn't 100% clear when I suggested using fflush() above. I believe that the problem is that you are being interrupted between the time that the characters are pushed to the screen and when the buffer is flushed. When the buffer is then actually truely flushed, you've effectively pushed your string twice.
Upvotes: 1
Reputation: 30489
I observed this issue on gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5), glib version 2.15 with O2
flag. Without any optimization flag, this issue is not observed.
Why the output is strange
The C language specification does not make reference to any particular compiler, operating system, or CPU. It makes reference to an abstract machine that is a generalization of actual systems. This abstract machine (atleast up to C99 specs) is single threaded. So standard libraries (including printf
) are not required to be thread safe by default. If you are using standard library functions across the threads (using some library for example posix libpthread), you are responsible for adding synchronization (mutex, semaphore, condvar etc) before accessing non-entrant standard library functions. If you don't, there may be surprising results from time to time and you should use at your own risk.
Some analysis at the environment where I can reproduce this issue
Analyzing the assembly generated for both version of flag, I can not find any significant difference (Onething noticeable, printf
s are converted to puts
)
Looking at the source for puts
int
_IO_puts (str)
const char *str;
{
int result = EOF;
_IO_size_t len = strlen (str);
_IO_acquire_lock (_IO_stdout);
if ((_IO_vtable_offset (_IO_stdout) != 0
|| _IO_fwide (_IO_stdout, -1) == -1)
&& _IO_sputn (_IO_stdout, str, len) == len
&& _IO_putc_unlocked ('\n', _IO_stdout) != EOF)
result = MIN (INT_MAX, len + 1);
_IO_release_lock (_IO_stdout);
return result;
}
#ifdef weak_alias
weak_alias (_IO_puts, puts)
#endif
It seems the problem lies in _IO_putc_unlocked('\n', _IO_stdout)
. This may flush the stream and may get killed before updating the stream state.
Learnings for multithreaded coding
When the main thread returns, it terminates the entire process. This includes all other threads. So signal all children threads to exit (or use pthread_kill
) and either make main thread exit with pthread_exit
or use pthread_join
.
Upvotes: 3
Reputation: 4438
In general you can't assume that printf and related memory structures are thread-safe. It depends on the way stdio library has been implemented. In particular, malfunctions may happen when threads and processes are terminating, since the runtime library usually flushes the output buffers before exiting. I have already seen such a sort of behavior, and the solution is usually a mutex or semaphore to protect the output operations (more precisely, to protect the accesses to FILE objects).
Upvotes: 1