1

In this segment of code, how can I create those threads without the use of the function pthread_join()? Using pthread_exit() didn't work.

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
typedef struct{
    char name[100];
    char search[100];
    pthread_t tid;
} mystruct;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
void* sfun(void *arg){
    mystruct *sfile= (mystruct *) arg;
    int fd=open(sfile->name,O_RDONLY);
    if(fd<0){
        printf("Error%s\n", sfile->name);
        pthread_exit(NULL);
    }
    int n=1;
    pthread_mutex_lock(&mutex);
    while(n!=0){
        n=match_line(fd,sfile->search);
        printf("%s:\t%d\n",sfile->name,n);
    }
    pthread_mutex_unlock(&mutex);
    close(fd);
    return NULL;
}

int main(int argc, char *argv[]){
    if(argc< 3){
        printf("Error\n");
        exit(1);
    }
    mystruct file[10];//max 10 threads
    int c;
    for(c=0;c<argc-2;c++){
    strcpy(file[c].search,argv[1]);
    strcpy(file[c].name,argv[c+2]);
    pthread_create(&file[c].tid,NULL,sfun,&file[c]);
    }
    for(c=0;c<argc-2;c++)
        pthread_join(file[c].tid,NULL);
    return 0;

}

Compiled with pthread_join():

./ppc "Sherlock" testfile1 testfile2 testfile12

testfile1:  5
testfile1:  762
testfile1:  960
testfile1:  977
testfile1:  1025
testfile1:  1034
testfile1:  1049
testfile1:  1068
testfile1:  1080
testfile1:  1123
testfile1:  0
testfile2:  3
testfile2:  90
testfile2:  170
testfile2:  179
testfile2:  473
testfile2:  643
testfile2:  760
testfile2:  811
testfile2:  836
testfile2:  978
testfile2:  0
testfile12: 5
testfile12: 762
testfile12: 960
testfile12: 977
testfile12: 1025
testfile12: 1034
testfile12: 1049
testfile12: 1068
testfile12: 1080
testfile12: 1123
testfile12: 1129
testfile12: 1216
testfile12: 1296
testfile12: 1305
testfile12: 1599
testfile12: 1769
testfile12: 1886
testfile12: 1937
testfile12: 1962
testfile12: 2104
testfile12: 0

with no pthread_join() it won't print anything!

Jeff Hammond
  • 5,374
  • 3
  • 28
  • 45
sh1ftz
  • 33
  • 1
  • 9
  • You can create threads without calling pthread_join simply by creating threads and not calling pthread_join. What's your real question? – user253751 Sep 20 '16 at 00:43
  • @immibis in this particular case the thread won't finish executing, I mean it won't run until the end. But with pthread_join() it runs. – sh1ftz Sep 20 '16 at 00:49
  • Yes, because in this particular case the program exits before the thread finishes. – user253751 Sep 20 '16 at 00:50
  • yes, so, how can I avoid that without the use of pthread_join() @immibis? – sh1ftz Sep 20 '16 at 00:55
  • 6
    Well you have to have some way to wait for your threads to finish before exiting. pthread_join is one obvious way, or you could use condition variables and mutexes to do the same thing, or have the threads write to a pipe when they're done and have the main thread read from it, or you could tell the user "please press enter when threads are done" and wait for them to press enter. But what's wrong with pthread_join? – user253751 Sep 20 '16 at 01:01
  • @immibis pthread_join() is the only way to do it properly; all of those other methods suffer from a race condition (because the thread is still running after it writes to a pipe (etc), and thus it's possible that the process will exit before the thread has a chance to finish cleaning up and going away). Only pthread_join() has the ability to hook into the thread implementation's post-cleanup routines to avoid the race. – Jeremy Friesner Sep 21 '16 at 04:45
  • @JeremyFriesner That's why you make writing to a pipe the last thing the thread does before any other cleanup. (Do pthreads have a way to register thread-exit actions? If they do then it wouldn't work.) – user253751 Sep 21 '16 at 04:45
  • @immibis the problem is, you can't make it the last thing it does: the last thing in your thread's entry-function isn't the last code the thread executes before it exits. Your entry-function is called by another function which typically does some additional cleanup after your entry-function has returned; and that cleanup may depend on global structures that the main thread might already be in the process of tearing down by then. – Jeremy Friesner Sep 21 '16 at 04:49

3 Answers3

3

You don't use pthread_join to create a thread, you use pthread_join to wait for a thread to exit.

Threads are sub-units of a process: they run in the same memory space as other threads within the same process. As a result, when the process ends, any running threads belonging to it are terminated, and exiting main (via exit or return) essentially ends the process.

pthreads has no api for detaching a thread from it's process.

If that's what you are trying to do, you will have to create processes, and should look at either posix_spawn or fork/exec.

If you are simply trying to create threads and not have to explicitly wait for them to each to terminate, you can call pthread_exit: http://man7.org/linux/man-pages/man3/pthread_exit.3.html

To allow other threads to continue execution, the main thread should terminate by calling pthread_exit() rather than exit(3).

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

void* tfun(void*)
{
    sleep(3);
    printf("Ni!\n");
    return NULL;
}

int main()
{
    pthread_t t;
    pthread_create(&t,NULL,&tfun,NULL);
    int ret = 0;
    pthread_exit(&ret);
}

Live demo: http://coliru.stacked-crooked.com/a/b47d3682008aed05

kfsone
  • 23,617
  • 2
  • 42
  • 74
1

how can I create those threads without the use of the function pthread_join()?

Not calling pthread_join() but leaving main() after having called pthread_create() exits the process and with this terminates all of its threads, most likely before they started to do anything useful.

To keep the process alive and still leave main(), do so by calling pthread_exit() instead of doing a return.

int main(int argc, char *argv[])
{
  ...

  pthread_exit(NULL);
}
alk
  • 69,737
  • 10
  • 105
  • 255
0

One alternative method for forcing your program to wait for all the threads to finish before it proceeds is to call pthread_barrier_wait(). Why can’t you use pthread_join(), though? Do you need to keep the threads alive?

Davislor
  • 14,674
  • 2
  • 34
  • 49