I want to create a program that creates a new thread each time a specific method is called. Here is my working code so far:
#define NUMBER_OF_THREADS 3
pthread_t threads[NUMBER_OF_THREADS];
pthread_attr_t attr;
void *BusyWork(void *t)
{
int i;
long tid;
tid = (long)t;
printf("Thread %ld running...\n",tid);
// ...
printf("Thread %ld completed...\n",tid);
pthread_exit((void*) t);
}
void createNewThread(int number){
printf("running createNewThread(%d)\n", number);
pthread_t tid;
int rc = pthread_create( &tid, &attr, BusyWork, (void *) (long)number);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
int main(int argc, char *argv[]) {
int i, rc;
//Set up thread attributes
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
//Arbitary amount of calls (My real program will call the createNewThread() funcion multiple unkown amount of times)
createNewThread(15);
createNewThread(27);
createNewThread(62);
createNewThread(500);
createNewThread(8864);
createNewThread(99999);
//Free attributes
pthread_attr_destroy(&attr);
//Wait for other threads still running
// HOW CAN I DO THIS????
/*for (i=0; i< NUMBER_OF_THREADS; i++){
rc = pthread_join( ??? , NULL); //TODO
if (rc){
printf("ERROR: return code from pthread_join() %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %d\n", i);
}*/
printf("Main: program completed. Exiting.\n");
pthread_exit(NULL); // (?) Is this part nessassary as we are on the main thread and soon to exit the program
return 0;
}
However as you can see in my code there is a few issues! For example, how can I wait for all processes to complete for the code I am using, as I am not keeping track of the thread number. Also when a thread "BusyWork" is done it does not clean up after it self and left as an orphan process.
One idea I had was to use a vector to keep track of each thread number and then use that for the final join at the end of main. However the problem with that is the array list can easily get very large and will never shrink even though a thread is complete.
Detach the threads, don't join them. Before you create a thread, increment a counter protected by a mutex. Right before a thread terminates, acquire the mutex and decrement the counter. Now you know all threads are done when the counter reads zero. You can use a condition variable to make the counter waitable if you like.
Related
In this code, I'm trying to create an array of threads. I've set the pthreads value to 1. In the for loop, the address, ID, and "created" gets printed, but the function never seems to execute as I don't get a print.
The seg fault actually happens at pthread_join at the bottom, but it certainly has to be caused by the creation since the function never runs, right? producers[0] is the only thread since I'm just testing 1. The create function passes an (ID address, NULL, the void * function(), and void* arguments) like it's supposed to. It has to be something obvious but I've tried to figure it out for so long I'm empty.
typedef struct ThreadStruct {
int threadIndex;
} ThreadStruct;
void *producer(void* ts){
printf("in producer\n");
FILE* inputfp = threadstruct->inputFiles[0];
hostname = (char*)malloc((MAXNAME+1)*sizeof(char));
while(fscanf(inputfp, hostname) > 0){
printf("%s",hostname);
}
return 0;
}
int main(int argc, char *argv[]){
int pthreads = atoi(argv[1]); //always 1
ThreadStruct threadstruct;
pthread_t producers[pthreads];
for(int i=0;i<pthreads;i++){
printf("in pthread loop\n");
printf("%p \n",&producers[i]);
printf("%ld \n",producers[i]);
pthread_create(&producers[i], NULL, producer, (void *) &threadstruct);
}
pthread_join(producers[0], NULL);
}
Your code works in my side and would not produce the seg fault.
Here is the print out info:
$ ./pthread
in pthread loop
0xffffcb70
6444554784
in pthread loop
in producer
0xffffcb78
64
in pthread loop
in producer
0xffffcb80
1
in pthread loop
in producer
0xffffcb88
4299166064
in pthread loop
in producer
0xffffcb90
6443761969
in pthread loop
in producer
0xffffcb98
6445451520
in pthread loop
in producer
0xffffcba0
314761761601
in producer
exit main thread
Your code here:
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
typedef struct ThreadStruct {
int threadIndex;
} ThreadStruct;
void *producer(void* ts){
printf("in producer\n");
return 0;
}
int main(int argc, char *argv[]){
int pthreads = 7;
ThreadStruct threadstruct;
pthread_t producers[pthreads];
for(int i=0;i<pthreads;i++){
printf("in pthread loop\n");
printf("%p \n",&producers[i]);
printf("%ld \n",producers[i]);
pthread_create(&producers[i], NULL, producer, (void *) &threadstruct);
}
pthread_join(producers[0], NULL);
printf("exit main thread\n");
}
you don't seem to check if the thread is actually created or not, in other words you don't seem to validate the return type of pthread_create and straight calling pthread_join probably leading to Undefined behavior, in case pthread_create fails.
pthread_create(&producers[i], NULL, producer, (void *) &threadstruct);
from pthread_join
The pthread_join() function shall fail if:
EINVAL The implementation has detected that the value specified by thread does not refer to a joinable thread.
ESRCH No thread could be found corresponding to that specified by the given thread ID.
however there are cases where pthread_join with invalid thread handle seg faults.
a piece of extract from the link above
"*Passing invalid handle to pthread_join is like passing invalid pointer to a system call.
The implementation may detect it and signal it in errno, but it may crash as
well.
There are 2 different POSIX threads implementations on Red Hat Linux
linuxthreads, where pthread_t handle is a small integer (and the number of
threads is substantially limited)
NPTL (the default, pthread_t is internally a pointer so that there are no
arbitrary thread limits)
You can request the old-fashioned threading library with LD_ASSUME_KERNEL=2.4.19
in the environment.
For NPTL where pthread_t is a pointer, pthread_join detects some invalid
handles where it can be done cheaply. But detecting all possible invalid
handles would be very costly (the implementation would basically have to take
a global lock and iterate over all currently running threads, comparing the
handle with each of them. With say 100000 running threads you can see how
costly it is).
This testcase works on SuSE since SuSE only ships the old-fashioned non-scalable
linuxthreads implementation.*"
from pthead_create
RETURN VALUE
On success, pthread_create() returns 0; on error, it returns an error number, and the contents of *thread are undefined.
perhaps something like this
if( pthread_create(&producers[i], NULL, producer, (void *) &threadstruct) ) {
perror("something wrong .. ");
exit(1);
}
Firstly check the return value of pthread_create() to check whether it was successful or not. For e.g
int ret = pthread_create(&producers[i], NULL, producer, (void *) &threadstruct);
if(ret) {
fprintf(stderr, "failed to create thread %s\n",strerror(ret));
exit(EXIT_FAILURE);
}
And Also it's advised to use pthread_join() for all the threads not only first thread, as if you want to wait for thread/s to terminate before further processing in main thread as mentioned here. Also check the return value of pthread_join().
Sample Code
#include<stdio.h>
#include<string.h>
#include<stdint.h>
#include<stdlib.h>
#include<pthread.h>
typedef struct ThreadStruct {
int threadIndex;
} ThreadStruct;
void *producer(void* ts){
printf("in producer\n");
return 0;
}
int main(int argc, char *argv[]){
int pthreads = 5;
int ret;
ThreadStruct threadstruct;
pthread_t producers[pthreads];
/* create threads */
for(intptr_t itr = 0;itr < pthreads; itr++){
printf("in pthread loop\n");
//printf("%p \n",&producers[itr]);
//printf("%ld \n",producers[itr]);
ret = pthread_create(&producers[itr], NULL, producer, (void *) &threadstruct);
if (ret) {
fprintf(stderr, "failed to create thread #%ld - %s\n",(long)itr, strerror(ret));
exit(EXIT_FAILURE);
}
}
/* join all threads */
for(intptr_t itr = 0; itr < pthreads; itr++){
printf("In main: joining thread #%ld\n", (long)itr);
ret = pthread_join(producers[itr], NULL);
if (ret) {
fprintf(stderr, "failed to join thread #%ld - %s\n",(long)itr, strerror(ret));
exit(EXIT_FAILURE);
}
}
//pthread_exit();
return 0;
}
it works in my system, hope it works for you also.
I am writing a c program to create three threads(1,2,3) such that at any given point of time only one thread must execute and print the output on console in the order 123123123123.........
I am making use of semaphore for synchronization.
I am having an issue with the code i have written. the code doesn't print it in the order 123123... the order is random and stops after a while.
#include<stdio.h>
#include<semaphore.h>
#include<pthread.h>
#include<unistd.h>
#include<assert.h>
#include<stdlib.h>
sem_t sem_1;
void *func1(void *arg){
int err1=0;
while(1){
err1=sem_wait(&sem_1);
assert(err1==0);
printf("thread 1\n");
}
//return NULL;
}
void *func2(void *arg){
int err2=0;
while(1){
err2=sem_wait(&sem_1);
assert(err2==0);
printf("thread 2\n");
}
// return NULL;
}
void *func3(void *arg){
int err3=0;
while(1){
err3=sem_wait(&sem_1);
assert(err3==0);
printf("thread 3\n");
}
// return NULL;
}
int main(){
pthread_t *t1,*t2,*t3;
int i=0,rc=0,c1=0,c2=0,c3=0;
t1=(pthread_t *)malloc(sizeof(*t1));
t2=(pthread_t *)malloc(sizeof(*t2));
t3=(pthread_t *)malloc(sizeof(*t3));
i=sem_init(&sem_1,0,1);
assert(i==0);
c1=pthread_create(t1,NULL,func1,NULL);
assert(c1==0);
c2=pthread_create(t2,NULL,func2,NULL);
assert(c2==0);
c3=pthread_create(t3,NULL,func3,NULL);
assert(c3==0);
while(1){
rc=sem_post(&sem_1);
assert(rc==0);
sleep(1);
}
return 0;
}
Why would you even expect them in in an order?
Your threads do things inbetween the different waits, and according to the system scheduler, these can take different amount of time.
printf is a buffered operation that gives you exclusive access to a shared resource. So in addition to your semaphore there is a hidden lock somewhere, that also regulates the progress of your threads. Don't expect the prints to appear in order, even if the calls themselves are.
Then, for the end, using assert here is really a very bad idea. All sem_t operations can (and will) fail spuriously, so it is really bad to abort, just because such a failure.
In fact, sem_t is really a low level tool, and you should never use it without checking return values and without having a fall back strategy if such a call fails.
Of course. I can't see any order related synchronization mechanism.
One of the options to achieve the strict order is to have one semaphore per thread:
sem_t sem[3];
// ...
while(1) {
for(n = 0; n < 3; n++) {
rc=sem_post(&sem[n]);
assert(rc==0);
}
sleep(1);
}
Below Code will help to solve the problem, one semaphore for each thread used to achieve synchronization. The initial value of the semaphore does the job. used usleep to launch thread in sequence manner for needed output. The same can be done by using Mutex lock and cond variables
//declaring semaphore
sem_t sema1;
sem_t sema2;
sem_t sema3;
void* t1(void *arg)
{
for(int j=0;j<10;j++)
{
sem_wait(&sema1);
printf("Thread 1 \n");
sem_post(&sema2);
}
printf("T1 return\n");
return NULL;
}
void* t2(void *arg)
{
for(int j=0;j<10;j++)
{
sem_wait(&sema2);
printf("Thread 2 \n");
sem_post(&sema3);
}
printf("T2 return\n");
return NULL;
}
void* t3(void *arg)
{
for(int j=0;j<10;j++)
{
sem_wait(&sema3);
printf("Thread 3 \n");
sem_post(&sema1);
}
printf("T3 return \n");
return NULL;
}
int main()
{
pthread_t tid1, tid2,tid3;
sem_init(&sema1,0,1);
sem_init(&sema2,0,0);
sem_init(&sema3,0,0);
pthread_create(&tid1, NULL, t1, NULL);
usleep(100);
pthread_create(&tid2, NULL, t2, NULL);
usleep(100);
pthread_create(&tid3, NULL, t3, NULL);
pthread_join(tid3, NULL);
pthread_join(tid2, NULL);
pthread_join(tid1, NULL);
sem_destroy(&sema1);
sem_destroy(&sema2);
sem_destroy(&sema3);
return 0;
}
I am looking for a very simple example to demonstrate a deadlock using pthread_join; however, this is not trivial.
I started with this:
void* joinit(void* tid)
{
pthread_t* tid_c = (pthread_t*)tid;
int retval = pthread_join(*tid_c, NULL);
printf("In joinit: tid = %d, retval = %d \n", *tid_c, retval);
return NULL;
}
int main()
{
pthread_t thread1;
pthread_t thread2;
pthread_create(&thread1, NULL, joinit, &thread2);
pthread_create(&thread2, NULL, joinit, &thread1);
pthread_join(thread2, NULL);
return 0;
}
But however, it says 'EINVAL' (invalid argument) because thread2 is not yet specified when pthread_create for thread1 is called.
Any ideas?
If you're just wanting to demonstrate that a pthread_join can cause a deadlock, you could do something similar to the following code:
#include <stdio.h>
#include <pthread.h>
void* joinit(void* tid)
{
printf("In %#x, waiting on %#x\n", pthread_self(), (*((pthread_t*)tid)));
pthread_join((*((pthread_t*)tid)), NULL);
printf("Leaving %#x\n", pthread_self());
return NULL;
}
int main(void)
{
pthread_t thread1 = pthread_self();
pthread_t thread2;
pthread_create(&thread2, NULL, joinit, &thread1);
joinit(&thread2);
return 0;
}
This will cause the main thread to wait on the spawned thread and the spawned thread to wait on the main thread (causing a guaranteed deadlock) without the need for extra locking primitives to clutter up what you are trying to demonstrate.
And to answer some of your questions more directly:
it says 'EINVAL' (invalid argument) because thread2 is not yet specified when pthread_create for thread1 is called.
... and from one of your comments ...
I tried this and it worked, but the problem is, it only works SOMETIMES because sometimes I get EINVAL again.
In your code, you call pthread_create consecutively to spawn the 2 threads:
pthread_create(&thread1, NULL, joinit, &thread2);
pthread_create(&thread2, NULL, joinit, &thread1);
In your joinit code, you grab the thread handle passed in to join on:
pthread_t* tid_c = (pthread_t*)tid;
int retval = pthread_join(*tid_c, NULL);
The reason this sometimes works and others you'll get EINVAL has to do with time slices allocated to each thread's context and sequencing. When the first pthread_create is called you will have a valid handle to thread1 after it returns but the handle to thread2 is not valid yet, at least not until the 2nd pthread_create is called.
To this, when a thread is created, the act of the thread coming "alive" (i.e. the thread function actually running) could take some extra time even though the thread handle returned is valid. In these instances, there is a chance one thread can execute more code than might be "expected". In your code, both pthread_create functions might happen to have been called in the time slice allocated for the main thread which could give each spawned thread enough "time" before hitting the pthread_join statement allowing tid_c to point to a valid handle; in the EINVAL case, pthread_create(&thread1, NULL, joinit, &thread2) was called and the spawned thread hit the pthread_join(*tid_c, NULL) before pthread_create(&thread2, NULL, joinit, &thread1) could give thread2 a valid handle (causing the error).
If you wanted to keep your code similar to how it is now, you would need to add a lock of some sort to ensure the threads don't exit or call anything prematurely:
#include <stdio.h>
#include <pthread.h>
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void* joinit(void* tid)
{
/* this can be above the lock because it will be valid after lock is acquired */
pthread_t* tid_c = (pthread_t*)tid;
int retval = -1;
pthread_mutex_lock(&lock);
pthread_mutex_unlock(&lock);
printf("%#x waiting on %#x\n", pthread_self(), *tid_c);
retval = pthread_join(*tid_c, NULL);
printf("In joinit: tid = %d, retval = %d \n", *tid_c, retval);
return NULL;
}
int main()
{
pthread_t thread1;
pthread_t thread2;
/* get the lock in the main thread FIRST */
pthread_mutex_lock(&lock);
pthread_create(&thread1, NULL, joinit, &thread2);
pthread_create(&thread2, NULL, joinit, &thread1);
/* by this point, both handles are "joinable", so unlock */
pthread_mutex_unlock(&lock);
/* can wait on either thread, but must wait on one so main thread doesn't exit */
pthread_join(thread2, NULL);
return 0;
}
Hope this can help.
The main reason for your error is that you have two threads each waiting for the same thread to terminate because of the call to pthread_join in main. Another problem is that you don't ensure each thread correctly sees the other thread's ID.
Fix it like this:
#include <stdio.h>
#include <pthread.h>
pthread_t thread1;
pthread_t thread2;
pthread_mutex_t mutex;
pthread_cond_t cond;
int go = 0;
void* joinit(void* ptr)
{
// wait until both thread IDs are known
pthread_mutex_lock(&mutex);
while (go == 0)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
pthread_t* tid_c = *((pthread_t**) ptr);
printf("About to wait\n");
int retval = pthread_join(*tid_c, NULL);
printf("In joinit: tid = %d, retval = %d \n", *tid_c, retval);
// tell the other threads we're done
pthread_mutex_lock(&mutex);
go++;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
return NULL;
}
int main()
{
// setup synchronization
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_create(&thread1, NULL, joinit, &thread2);
pthread_create(&thread2, NULL, joinit, &thread1);
// tell the threads to go
pthread_mutex_lock(&mutex);
go = 1;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
// wait for both threads to finish
pthread_mutex_lock(&mutex);
while (go != 3)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
return 0;
}
So I have code here which makes two kinds of threads. One kind "produces" data and the other one "consumes" it. There can only be a certain amount of data that can exist at any one time, so the Producers will pause producing once there is a certain amount of data created (ie, when sharedData = BUFFER), and the consumers will pause when sharedData = 0. There is also only so much data that can be made (amount stored in dataleft), and once all the data has been made and consumed, the program should end.
For some reason, the printf() lines I have at the end of the code don't seem to ever trigger. I can't tell if the threads are closed properly or not because of this. It feels like I've done something really stupid, but I can't see the issue.
A couple of definitions at the start:
#define NUMCONSUMERS 4
#define NUMPRODUCERS 4
#define PACKETS 10
#define tryMainlock pthread_mutex_trylock(&dataMutex)
#define openMainlock pthread_mutex_lock(&dataMutex)
#define closeMainlock pthread_mutex_unlock(&dataMutex)
#define waitMainlock pthread_cond_wait(&dataPresentCondition, &dataMutex);
#define signalMainlock pthread_cond_signal(&dataPresentCondition);
#define trydatalock pthread_mutex_trylock(&IsthereDataleft)
#define opendatalock pthread_mutex_lock(&IsthereDataleft)
#define closedatalock pthread_mutex_unlock(&IsthereDataleft)
pthread_mutex_t dataMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t dataPresentCondition = PTHREAD_COND_INITIALIZER;
pthread_mutex_t IsthereDataleft = PTHREAD_MUTEX_INITIALIZER;
int sharedData=0; //amount of data present
int BUFFER = 5;
int dataleft=PACKETS;
The Main Function:
int main(int argc, char **argv)
{
int rc;
int i;
pthread_t consumer[NUMCONSUMERS];
pthread_t producer[NUMPRODUCERS];
rc = opendatalock; //lock to determine whether there's any point waiting for data
for (i=0; i <NUMPRODUCERS; i++) { //Build up the producers
rc = pthread_create(&producer[i], NULL, Producer, (void *)i);
if (rc)
printf("Error building Producer Thread: %x\n", i);
}
for (i=0; i <NUMCONSUMERS; i++) { //Build up the consumers
rc = pthread_create(&consumer[i], NULL, Consumer, (void *)i);
if (rc)
printf("Error building Consumer Thread: %x\n", i);
}
printf("All Producers and Consumers created\n");
for (i=0; i <NUMPRODUCERS; i++) { //Join up the producers
rc = pthread_join(producer[i], NULL);
if (rc)
printf("Error: Producer %x: Failed to join\n", i);
}
rc = closedatalock; //producers finished, no data left to make
printf("datalock closed, consumers finishing...\n");
for (i=0; i <NUMCONSUMERS; i++) { //Join up the consumers
rc = pthread_join(consumer[i], NULL);
if (rc)
printf("Error: Consumer %x: Failed to join\n", i);
}
rc = pthread_mutex_destroy(&dataMutex);
rc = pthread_cond_destroy(&dataPresentCondition);
rc = pthread_mutex_destroy(&IsthereDataleft);
printf("All Threads finished. Exiting....\n");
return 0;
}
The Consumer Thread:
void *Consumer(void *threadid){
int rc;
printf("Consumer Thread %x: Created\n", (int)threadid);
while (1)
{
printf("Consumer %x: Entering Loop\n", (int)threadid);
rc = openMainlock; //take hold of main lock
if (rc)
{
printf("Consumer %x: Waiting...\n", (int)threadid);
rc = waitMainlock; //if main lock is taken, wait
if (rc) //if wait fails, exit the thread.
{
printf("Consumer Thread %x: wait for Main Lock failed\n", threadid);
exit(0);
}
}
while (sharedData == 0) //if the buffer is empty
{
rc = trydatalock;
if (!rc)
{
printf("Consumer %x: Completed. Exiting...\n");
exit(0);
}
rc = closeMainlock;
if (rc)
{
printf("code.\n");
}
rc = waitMainlock;
if (rc)
{
printf("code.\n");
}
}
sharedData--;
rc = closeMainlock;
rc = signalMainlock;
if (rc)
{
printf("code.\n");
}
printf("Consumer %x: Releasing Lock\n", (int)threadid);
}
}
And the Producer Thread:
void *Producer(void *threadid){
int rc;
printf("Producer Thread %x: Created\n", (int)threadid);
while (1)
{
printf("Producer %x: Entering Loop\n", (int)threadid);
rc = openMainlock; //take hold of the lock
if (rc) //if lock is currently being used by a consumer or a producer
{
printf("Producer %x: Waiting...\n", (int)threadid);
rc = waitMainlock; //wait here until lock is released
if (rc)
{
printf("Producer Thread %x: wait for Main Lock failed\n", threadid);
exit(0);
}
}
if (!dataleft) //If there's no data left to add to the stream, close the thread
{
printf("Producer Thread %x: Completed, exiting...\n", (int)threadid);
exit(0);
}
while (sharedData >=BUFFER)
{
rc = closeMainlock;
if (rc)
{
printf("code.\n");
}
rc = waitMainlock;
if (rc)
{
printf("code.\n");
}
}
printf("Producer %x: Lock Acquired\n", (int)threadid);
sharedData++;
dataleft--;
rc = closeMainlock;
rc = signalMainlock;
if (rc)
{
printf("code.\n");
}
printf("Producer %x: Releasing Lock\n", (int)threadid);
}
}
Check out this piece of code:
if (!rc)
{
printf("Consumer %x: Completed. Exiting...\n");
exit(0);
}
If the consumer has finished, the process(!) is terminated. You need to use pthread_exit() instead, or simply return from the thread function.
Then, there is also
../nptl/pthread_mutex_lock.c:80:
__pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed.
which I got a few times running the code. That could be caused by e.g. double unlock or some other invalid use. I'd start with cleaning up the weird macros, so that you have a free view on the logic of the program itself.
Also, one important advise concerning mutexes: Always document precisely which data should be protected by the mutex. The point is that it's not always clear and getting this wrong means that you accidentally access data without synchronization. In order to make this very clear, use a structure like here:
struct {
pthread_mutex_t mutex;
pthread_cond_t cond;
int data;
} synced_data = {
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_COND_INITIALIZER,
0
};
Actually, it's not just about the shared data that documentation is important. Consider for example IsthereDataleft: This is a mutex but it doesn't guard anything, right? Instead, it is used to signal to the started threads that there is nothing left to do, right? Documenting this not only helps others to understand your code but it makes sure that you understand yourself what the intention is. Sometimes, while trying to explain it, you will then find yourself that something doesn't make sense.
Something seems to be awry with your use of openMainlock, which expands to a pthread_mutex_lock call.
One one hand, you shouldn't expect to ever get a non-zero return value from openMainlock: pthread_mutex_lock should either return zero (lock acquired) or block, unless the mutex is not initialised or is an error-checking mutex.
Further, once the lock is acquired, if the producer is done, i.e. dataleft is zero, the thread calls exit(0), which will terminate the whole process rather than terminating the thread. pthread_exit should be used instead, or just return from the function, but note that at this point you still own the main lock, which won't be released.
i have this piece of code:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <time.h>
int number;
pthread_mutex_t *mutex;
pthread_t *threads;
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
time_t rawtime;
struct tm * time_start;
time ( &rawtime );
time_start = localtime ( &rawtime );
printf ( "The number %ld thread is created at time %s \n",tid, asctime (time_start));
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
int i,rc;
printf("give threads");
scanf("%d",&number);
mutex = calloc( number, sizeof(*mutex));
threads = calloc(number, sizeof(*threads));
for (i = 0; i < number;i++) {
pthread_mutex_init( &mutex[i],NULL);
}
for(i=0; i<number; i++){
printf("In main: creating thread %d\n", i);
rc = pthread_create(&threads[i], NULL, PrintHello, (void *)i);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
return 0;
}
The purpose of this code is to ask the user to give the number of the threads that it is going to create and after the creation of the threads,the thread itself will print 2 messages saying the number of the thread and the time that it was created.
The problem is that inside the main the message "In main: creating thread" is showing up but the message inside the threads sometimes does not.
For example, it would create 3 threads and only 1 thread will show up its message and that thread also will not show up the time that was created. I dont know if there is something wrong with the code.
Root Cause:
Your main() exits before the child threads get an opportunity to complete their task.
Solution:
You need to make sure that the main() waits until all the threads have completed their work.
You need to use:
pthread_join()
to achieve this functionality. Add the following before returning from main():
for(i=0; i<number; i++)
{
pthread_join(threads[i], NULL);
}
Other problems:
You allocate memory dynamically but never deallocate it. Eventhough, the OS reclaims the memory once your program returns. It is a good practice to do so explicitly.
You created a mutex but you neither use it, nor deallocate it. But that seems to be code in progress.
Return from main() is equivalent to calling exit(...), which terminates the whole process. You may use pthread_join() to wait for each non-main thread, like another answer advises, or you may call pthread_exit(NULL) in the end of your main(): it would exit the initial thread, but other threads will continue to run.