How to remove a terminated thread from a running process - c

Sorry if the question is quite basic but I've looked up the QNX documentation, trying every function that can terminate a thread which doesn't work.
I have this test program that creates 2 thread and makes one of them (the one with the main()) run forever while the other terminates on pthread_exit()
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void *thread(void *arg) {
char *ret;
if ((ret = (char*) malloc(20)) == NULL) {
perror("malloc() error");
exit(2);
}
int input;
printf("type a num to exit\n");
scanf("%d",&input);
strcpy(ret, "This is a test");
pthread_exit(ret);
}
int main() {
pthread_t thid;
void *ret;
if (pthread_create(&thid, NULL, thread, NULL) != 0) {
perror("pthread_create() error");
exit(1);
}
while(1){
}
if (pthread_join(thid, &ret) != 0) {
perror("pthread_create() error");
exit(3);
}
printf("thread exited with '%s'\n", ret);
}
Upon start-up, typing pidin | grep will return two threads in one process as expected. But after one thread is terminated, running pidin | grep again still shows two threads, with one of them having DEAD status. I know that the DEAD thread cannot be accessed anymore unless joined when they are not detached. However, I want to know if there is a way to exit one thread and completely remove it from the process, so typing pidin | grep on the process again will only show one thread running instead of two.
Thanks.

Related

C - threads and processes - prevent zombies

I'm implementing a function which receives a parsed-to-array command lines ("./waiter 20 &" will be parsed, and the function will receive the array
{"./waiter","20","&"} for example).
If the last argument is &, the process should run in the background.
To prevent zombies, I need to use a new thread that will wait for the child process.
The attached code is my working program, and all my efforts to add a new thread that will wait for the child process failed.
Anyone can guide me?
Attaching the code, with some of the leftovers of my unsuccessful tries.
(the function is process_arglist)
update: after a lot of tries using what suggested here, its still failing and im not sure why. updated code attached.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
void func(void* ptr) {
pid_t* mypid = (pid_t*)ptr;
waitpid(*mypid);
pthread_detach(pthread_self());
}
int process_arglist(int count, char** arglist){
int isBackground = 0;
pid_t pid;
int status;
char** parsedList;
if (strcmp(arglist[count-1],"&") == 0) {
printf("###we are in the & situation\n");
parsedList = (char**)malloc((count-1)*sizeof(char*));
if (parsedList == NULL) {
printf( "Error: malloc failed - %s\n", strerror(errno));
}
int i;
for (i=0;i<count-1;i++){
parsedList[i] = arglist[i];
}
/*printf("parsed list:\n");
for (i=0;i<count-1;i++) {
printf(" %d: %s\n", i,parsedList[i]);
}*/
if ((pid = fork()) < 0) { /* fork a child process */
printf( "Error: fork failed");
exit(0);
} else if (pid == 0) { /* for the child process: */
if (execvp(*parsedList,parsedList) < 0) { /* execute the command */
printf( "Error: execvp failed - %s\n", strerror(errno));
exit(0);
}
} else {
pthread_t thread;
pthread_create(&thread, NULL, (void*) &func, (void*) &pid);
}
} else {
if ((pid = fork()) < 0) { /* fork a child process */
printf( "Error: forking child process failed - %s\n", strerror(errno));
exit(0);
}
else if (pid == 0) { /* for the child process: */
if (execvp(*arglist,arglist) < 0) { /* execute the command */
printf( "Error: execvp failed - %s\n", strerror(errno));
exit(0);
}
}
else { /* for the parent: */
while (waitpid(&status) != pid); /* wait for completion */
}
}
}
First, switch from calling wait to calling waitpid. Otherwise, if you have more than one thread waiting, they'll steal each other's notifications.
Second, break the call to waitpid into its own function that takes the PID to wait for as a parameter. Cast it through void *, since that's what's used for thread parameters.
Third, change the call to the function to a call to pthread_create, casting the PID to wait for to a void * to pass to the newly-created thread.
Lastly, have the thread detach itself, since there won't be anything waiting for the thread to terminate.

Thread not hitting thread function every time

I am trying to make a program that takes several files, appends them all into one big file. Each append has to be done by a separate thread.
/*
This program creates appends several files together
*/
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
pthread_t *tids;
void *threadout(void *num);
int main(int argc, char *argv[])
{
int numOfFiles = atoi(argv[2]);
int error;
int index;
sem_t sem;
//Used for output file
int outFile;
//Checking to make sure there is the correct number of arguments
if (argc != 4)
{
printf("%s \n", "Wrong number of arguments, exiting program.");
return 1;
}
//checking to make sure there are at least two files to append
if (numOfFiles < 2)
{
printf("%s \n", "Cannot append 1 file or less.");
return 1;
}
//opening/creating file
outFile = open(argv[3], O_WRONLY | O_CREAT, S_IRUSR);
///****************** Allocate space for thread ids ******************/
tids = (pthread_t *)calloc(numOfFiles, sizeof(pthread_t));
if (tids == NULL)
{
perror("Failed to allocate memory for thread IDs");
return 1;
}
if (sem_init(&sem, 0, 1) == -1)
{
perror("Failed to initialize semaphore");
return 1;
}
/****************** Create threads *********************************/
for (index = 0; index < numOfFiles; index++)
{
if (error = pthread_create(tids + index, NULL, threadout, &index))
{
fprintf(stderr, "Failed to create thread:%s\n", strerror(error));
return 1;
}
}
return 0;
}
void * threadout(void *num)
{
printf("Hello");
return NULL;
}
Near the bottom of the program I do the actual creating of the threads. The first thing the thread should do is hit the "threadout" function. However the only way I can get anything to print is if I say to create a large number of threads. So if I tell my program to create 5000 threads, "Hello" will be printed. Not 5000 times though. If I asked it to create 10 threads nothing is printed. Am I doing something wrong when I invoke "threadout"? Thanks
Returning from main causes your entire program to exit, even if other threads are running.
Your main function exits when all threads are started. If you're starting lots of threads, this leaves enough time for the first ones to print. If you're starting few threads, it returns before the first ones get to print anything.
You might want to use pthread_join (called once per thread) to wait for all threads to terminate.

Sending signal to all threads

I'm trying to create simple signal handling - let's say something like terminating the process. I have three separate threads in my program + main thread.
The problem is that invoking the signal causes the current thread to terminate, while the others are still running.
How can I send the signal to the remaining threads? How can I differentiate these signals while sending them?
I have to use FIFO here by the way.
Here's what I've got so far:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/stat.h>
#include <pthread.h>
#include <string.h>
#include <signal.h>
int first[2];
int second[2];
#define FIFO_FILE "tmp/myfifo"
void *input(void *ptr)
{
char str[100], fifo[100];
int length;
FILE *fp;
while(1)
{
fp = fopen(FIFO_FILE, "r");
fgets(fifo, 100, fp);
if(fifo == "s1")
{
printf("SIGNAL 1!!!");
exit(1);
}
printf("Enter the message: ");
fflush(stdout);
length = read(STDIN_FILENO, str, sizeof(str));
if(str[0] == ';')
exit(2);
if(length <= 0)
{
if(length == -1)
perror("read");
close(first[1]);
exit(2);
}
if(write(first[1], str, length) != length)
{
perror("write");
exit(2);
}
}
}
void *countChars(void *ptr)
{
char str[100], fifo[100];
int length, count = 0;
FILE *fp;
while(1)
{
fp = fopen(FIFO_FILE, "r");
fgets(fifo, 100, fp);
if(fifo == "s1")
{
printf("SIGNAL 1!!!");
exit(1);
}
length = read(first[0], str, sizeof(str));
if(length <= 0)
{
if(length == -1)
perror("read");
close(first[0]);
close(second[1]);
exit(2);
}
if(write(STDOUT_FILENO, str, length) != length)
{
perror("write");
exit(2);
}
while(str[count] != '\n') count++;
write(second[1], &count, sizeof(count));
count = 0;
}
}
void *output(void *ptr)
{
int length, count = 0;
char fifo[100];
FILE *fp;
while(1)
{
fp = fopen(FIFO_FILE, "r");
fgets(fifo, 100, fp);
if(fifo == "s1")
{
printf("SIGNAL 1!!!");
exit(1);
}
length = read(second[0], &count, sizeof(count));
if(length < sizeof(count))
{
close(second[0]);
exit(2);
}
printf("Number of characters: %d\n", count);
}
}
void s1_handler(int signo)
{
FILE *fp;
if((fp = fopen(FIFO_FILE, "wb")) == NULL)
{
perror("fopen");
exit(2);
}
fputs("s1", fp);
fclose(fp);
}
int main()
{
pthread_t t1, t2, t3;
if(pipe(first) == -1)
{
printf("First pipe error");
exit(1);
}
if(pipe(second) == -1)
{
printf("Second pipe error");
exit(1);
}
pthread_create(&t1, NULL, input, NULL);
pthread_create(&t2, NULL, countChars, NULL);
pthread_create(&t3, NULL, output, NULL);
if(signal(SIGINT, s1_handler) == SIG_ERR)
{
printf("Cant catch SIGINT\n");
}
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
return 0;
}
You have quite a few (conceptual) errors in your program.
Signals: Standard signals (i.e. non-realtime signals like SIGINT) are not queued. Your process will only receive one and any further signals (of the same type) will be thrown away until the one already delivered is somehow processed. Signals (most, anyway) are delivered to the process as a whole. In the absence of your program taking actions to do otherwise, the signal will be delivered to an arbitrary thread within the process. You can resend a signal you catch to your other threads with pthread_kill but this will require you to make each thread id available to every other thread by using, for instance, a global table of TIDs. It is unclear what you are really trying to accomplish with your program but that is almost certainly not what you want to do.
FIFOs: You seem to know that using FIFOs to communicate between threads is a dubious design but if you were told to use them then you have to use them correctly.
(1) When FIFOs are opened (w/o specifying non-blocking mode) the open is going to block until there is both a reader and a writer on each end of the FIFO. This means all 3 of your threads will block on their respective FIFO open calls until your signal handler - see problems with that below - runs and opens the FIFO for writing.
(2) Even when you get past the opens, only one thread is going to read and consume the string that the signal handler wrote. The other threads are going to sit blocking trying to read an empty FIFO and will never process anything. Currently you are just calling exit in the thread that reads the FIFO, which will end the program, but is that what you are really going for?
(3) There is no need to open the FIFO in each thread. You can do this that before creating the threads and either pass the FIFO file descriptor to each thread or just make it global.
(4) You are opening (and not closing) the FIFO in each thread every time through your while(1) loops. You will run out of file descriptors very quickly that way.
Signal Handler: You should not use non-async safe calls in a signal handler. You have at least 3 - fopen, fputs, fclose. Ideally you want to do very simple things, like just set a global switch, in a signal handler and get out. So if this is anything more than a brain dead class assignment you should rethink this entirely.
I would suggest elaborating exactly what your goal is for the program and you can get some advice on how to reach it.
Only one thread receives the signal! Which one? See the quoted details from:
http://www.linuxprogrammingblog.com/all-about-linux-signals?page=11
Which thread receives the signal?
This is the most interesting question. There are two cases:
Process-directed signals (sent to a PID using functions like kill(2)).
Threads have their separate signal mask which can be manipulated using pthread_sigmask(2) similary to sigprocmask(2), so such signal is not delivered to a thread that has this signal blocked. It's delivered to one of threads in the process with this signal unblocked. It's unspecified which thread will get it. If all threads have the signal blocked, it's queued in the per-process queue. If there is no signal handler defined for the signal and the default action is to terminate the process with or without dumping the core the whole process is terminated.
Thread-directed signals. There is a special function to send a signal to a specific thread: pthread_kill(2). It can be used to send a signal from one thread to another (or itself). This way the signal will be delivered or queued for the specific thread. There are also per-thread directed signals generated by the operating system like SIGSEGV. If there is no signal handler defined for a signal that default's action is to terminate the process, a thread-directed signal terminated the whole process.

Pthread function starting in C

I'm actually new in processes, threads, semaphores, ipc etc(shortly operating system operations on Linux)... My problem is that I compile my code and It simply gets stuck at so funny points. Processes are executed, but they can't enter their threads' function. After that, program directly ends without doing something. I really can't figure out the problem is here or everything have problem. I don't know.
#define _GNU_SOURCE
#include <sys/types.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
void * function1(void *ptr)
{
printf("Function 1\n"); //!Test prints
printf("Index is %d",*((int *)ptr));
sleep(1);
pthread_exit(NULL);
}
void * function2(void *ptr)
{
printf("Function 2\n"); //!Test prints
printf("Index is %d",*((int *)ptr));
sleep(2);
pthread_exit(NULL);
}
int main(){
//...
int *index;
int i;
pid_t f;
int number_of_process=5;
pthread_t thread1, thread2;
//...
for(i=0; i<number_of_process; i++)
{
f=fork();
if(f==-1)
{
printf("Fork Error!!\n");
exit(1);
}
if(f==0) //To block child processes re-enter
{
*index = i; //I store index number for each process here. I'll need them in the thread functions
break;
}
}
/*******************PARENT PROCESS********************/
if(f!=0){
// wait for all children to exit
while (f = waitpid (-1, NULL, 0)){
if (errno == ECHILD)
break;
}
exit(0);
}
/*******************CHILD PROCESS*********************/
else{
pthread_create(&thread1,NULL,function1,(void *)index);
pthread_create(&thread2,NULL,function2,(void *)index);
}
}
Processes are executed, but they can't enter their threads' function.
After that, program directly ends without doing something.
That's because the main thread (i.e. child process created by fork()) doesn't wait for the threads to complete their execution. So it gives you the impression that the program exits without calling all pthread functions.
Use pthread_join() after creating threads:
...
pthread_create(&thread1,NULL,function1,(void *)index);
pthread_create(&thread2,NULL,function2,(void *)index);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
...
The output may be interleaved due to threads printing without any synchronization.

Problem while compiling pthreads program

I tried to compile this simple pthreads program with this command
$ gcc -pthread -o pthreads pthreads.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
void *myThread(void *arg);
int main()
{
pthread_t mythread;
int ret;
ret = pthread_create( &mythread, NULL, myThread, NULL );
if (ret != 0){
printf( "Can't create pthread: %s", strerror(errno));
exit(-1);
}
return 0;
}
void *myThread(void *arg){
// Thread code goes here..
printf("OK! NOW ON THE THREAD\n");
pthread_exit(NULL);
}
but when trying ./pthreads there is no output presented!!
You need to wait for the thread to finish. Otherwise you risk exiting before the thread starts executing.
...
pthread_create( &mythread, NULL, myThread, NULL );
...
// Wait for the thread to finish.
pthread_join( mythread, NULL);
You didn't wait for your thread to finish. You need to use pthread_join().
You problem comes from the fact that you're main thread is returning from main, and thus calling exit (or _exit). All running thread are killed when the program exit. In this case, the worker thread didn't have the time to execute before it is killed.
You can use pthread_join to wait for the completion of the thread before returning from main.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
void *myThread(void *arg);
int main()
{
void* thread_return;
pthread_t mythread;
int ret;
ret = pthread_create(&mythread, NULL, myThread, NULL);
if (ret != 0)
{
printf("Can't create pthread: %s\n", strerror(errno));
exit(-1);
}
ret = pthread_join(mythread, &thread_return);
if (ret != 0)
{
printf("Can't join pthread: %s\n", strerror(errno));
exit(-1);
}
return 0;
}
void *myThread(void *arg)
{
printf("OK! NOW ON THE THREAD\n");
pthread_exit(NULL);
}
Sanjit's answer is certainly correct, but for the sake of enlarging your threads toolbox, you might also look at pthread_barrier_wait. When you have a simple program with a lot of threads and main looks like "start all worker threads and wait for them to finish", having main and all the workers simply wait on a barrier can be a nice way to avoid having to store all the worker thread ids and join them in a for loop. Barriers also have a lot of other neat uses that sometimes let you avoid unnecessary complexity from doing the same things with mutexes and condition variables.

Resources