C - Threads using execl suicides itself - c

here's my problem: my code should execute all the executable files (i.e. all the binaries and all the scripts) in the current directory, concurrently.
Here's the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <dirent.h>
/* struct created for passing arguments at every thread */
struct thread_data {
long thread_id;
char *nome_file;
};
/* task of every thread */
void *work(void *thread_args) {
long tid;
char *name;
struct thread_data *my_data;
my_data = (struct thread_data *)thread_args;
tid = my_data -> thread_id;
name = my_data -> nome_file;
printf("thread number %ld get file %s\n", tid, name);
execl(name, name, (char *)0);
printf("execl failed\n");
pthread_exit(NULL);
}
int filter(const struct dirent *entry) {
/* Filter for scandir(): I consider only the regular files */
if(entry -> d_type == DT_REG)
return 1;
else
return 0;
}
int main() {
int n, rc;
long t;
struct dirent **namelist;
pthread_attr_t attr;
void *status;
/* Number of regular files in the current directory */
n = scandir(".", &namelist, filter, alphasort);
if(n < 0) {
perror("scandir()");
exit(EXIT_FAILURE);
}
/* How many threads? */
pthread_t thread[n];
/* Every thread will receive one instance of the struct thread_data */
struct thread_data thread_data_array[n];
/* With this, I'm sure my threads will be joinable */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(t=0; t<n; t++) {
printf("Main: creating thread %ld\n", t);
/* Filling the arguments in the struct */
thread_data_array[t].thread_id = t;
thread_data_array[t].nome_file = namelist[t] -> d_name;
rc = pthread_create(&thread[t], &attr, work, (void *)&thread_data_array[t]);
if(rc) {
printf("ERROR: pthread_create() is %d\n", rc);
exit(EXIT_FAILURE);
}
}
pthread_attr_destroy(&attr);
for(t=0; t<n; t++) {
rc = pthread_join(thread[t], &status);
if(rc) {
printf("ERROR: pthread_join() is %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Main: join succeeded on thread %ld\n", t);
}
printf("Main: program finished. Quitting...\n");
pthread_exit(NULL);
}
My program successfully reads the regular files in the current dir, and every thread get one file per time, but when the first binary or script is executed, the program quits!
Here's an example of its execution...
Main: creating thread 0
Main: creating thread 1
Main: creating thread 2
Main: creating thread 3
Main: creating thread 4
Main: creating thread 5
Main: creating thread 6
thread number 0 get file slide.pdf
execl failed
thread number 1 get file hello.sh
Congrats, you executed this script, I'm hello.sh!
And then, he won't continue the execution with other files. Perhaps the error is in the execl return value in case of success...

All of the exec-family functions replace the current process (not thread) by the named executable when they succeed; the only way they return is on failure. You should be using either fork followed by execl, or preferably, posix_spawn.

Related

Segfault with pthread and concurrency in C

I'm trying to have a thread, that waits until a task is assigned and then will do it, however I'm running into complications.
#include "dispatchQueue.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t mutex;
pthread_cond_t cond;
task_t *task;
void test1() {
sleep(1);
printf("test1 running\n");
}
void* do_stuff(void *args) {
printf("in do stuff\n");
pthread_mutex_lock(&mutex);
printf("after do stuff has lock\n");
task_t *task = (task_t *)args;
(task->work) (task->params);
pthread_mutex_unlock(&mutex);
}
int main(int argc, char** argv) {
pthread_t thread;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_mutex_lock(&mutex);
printf("after main gets lock\n");
pthread_create(&thread, NULL, do_stuff, task);
task = task_create(test1, NULL, "test1");
pthread_mutex_unlock(&mutex);
printf("after main unlocks \n");
pthread_join(thread, NULL);
}
The above code will give a segfault, however if I switch the lines pthread_create and task = task_create(), then it works fine. I'm not familiar with C at all, so I'm wondering why this is?
This is how task is created if that helps, at this point I'm pretty sure it's a problem with the way I'm using pthreads.
task_t *task_create(void (*work)(void *), void *param, char* name) {
task_t *task_ptr = malloc(sizeof(task_t));
if (task_ptr == NULL) {
fprintf(stderr, "Out of memory creating a new task!\n");
return NULL;
}
task_ptr->work = work;
task_ptr->params = param;
strcpy(task_ptr->name, name);
return task_ptr;
}
pthread_create(&thread, NULL, do_stuff, task);
task = task_create(test1, NULL, "test1");
You're passing junk to the thread. You haven't set task to any particular value here, yet you pass it to the thread as a parameter.
void* do_stuff(void *args) { // *** args is garbage here
printf("in do stuff\n");
pthread_mutex_lock(&mutex);
printf("after do stuff has lock\n");
task_t *task = (task_t *)args; // ** So task is garbage here
(task->work) (task->params);
pthread_mutex_unlock(&mutex);
}
Here, you initialize task from args. But args has a garbage value.
If you have some kind of collection that's going to track what tasks a thread is going to work on, you have to pass the thread a parameter that allows it to reliably find that collection. In this particular case, &task would work.

What will happen if pthread_cond_wait() competes with another thread?

Here is a program bellow and its function is counting words in two files with 3 threads(one is the main thread, one for file1, and one for file2).
I know that pthread_cond_wait(&flag, &lock) will lock the mutex before it returns. But what will happen if another thread locks the mutex first?
In this program:
main thread calls pthread_cond_wait, it unlocks the mutex.
thread1 locks the mutex, after doing something, it calls pthread_cond_signal.
main thread got the signal sent by thread1, then it wants to lock the mutex, but the mutex was lock by thread1, so the main thread is blocked.
thread1 unlocks the mutex.
main thread(pthread_cond_wait) now can lock the mutex and return.
But! At this moment(step 5), what will happen if another thread, say thread2, locks the mutex first before pthread_cond_wait locks the mutex? The main thread is still blocked? If it does, then
this program is a buggy program, all the threads(main thread and thread2) will be blocked. But I have run it a lot of times, it worked fine.
Update My Question: Will other threads lock the mutex during the period between the moment that pthread_cond_wait gets the signal sent by pthread_cond_signal requiring the mutex to lock and the moment that pthread_cond_wait locks the mutex.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <ctype.h>
struct arg_set { /* two values int one arg */
char *filename; /* file to examine */
int count; /* number of words */
int code;
};
struct arg_set *mailbox = NULL;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t flag = PTHREAD_COND_INITIALIZER;
void *count_words(void *);
int main(int argc, char *argv[])
{
pthread_t t1, t2; /* two threads */
struct arg_set args1, args2; /* two argsets */
int reports_int = 0;
int total_words = 0;
if (argc != 3) {
fprintf(stderr, "usage: %s file1 file2", argv[0]);
exit(1);
}
pthread_mutex_lock(&lock);
args1.filename = argv[1];
args1.count = 0;
args1.code = 1;
pthread_create(&t1, NULL, count_words, (void *)&args1);
args2.filename = argv[2];
args2.count = 0;
args2.code = 2;
pthread_create(&t2, NULL, count_words, (void *)&args2);
while (reports_int < 2) {
printf("MAIN: waiting for flag to go up\n");
pthread_cond_wait(&flag, &lock);
printf("MAIN: Wow! flag was raised, I have the lock\n");
printf("%7d: %s\n", mailbox->count, mailbox->filename);
total_words += mailbox->count;
if (mailbox == &args1)
pthread_join(t1, NULL);
if (mailbox == &args2)
pthread_join(t2, NULL);
mailbox = NULL;
pthread_cond_signal(&flag);
reports_int++;
}
printf("%7d: total words\n", total_words);
return 0;
}
void *count_words(void *a)
{
struct arg_set *args = a;
FILE *fp;
int c, prevc = '\0';
if ((fp = fopen(args->filename, "r")) != NULL) {
while ((c = getc(fp)) != EOF) {
if (!isalnum(c) && isalnum(prevc))
args->count++;
prevc = c;
}
fclose(fp);
} else
perror(args->filename);
printf("COUNT %d: waiting to get lock\n", args->code);
pthread_mutex_lock(&lock);
printf("COUNT %d: have lock, storing data\n", args->code);
if (mailbox != NULL)
pthread_cond_wait(&flag, &lock);
mailbox = args;
printf("COUNT %d: raising flag\n", args->code);
pthread_cond_signal(&flag);
printf("COUNT %d: unlocking box\n", args->code);
pthread_mutex_unlock(&lock);
return NULL;
}

pthread_key_create() - When does the `destructor` function invoked?

I wrote a program to learn about thread-specific data on Linux (Linux 3.13.0-24-generic #46-Ubuntu), as following.
I try to print thread id in the destructor function passed to pthread_key_create(), but it seems only sub threads succeed to print, but the main thread didn't print that info.
My question is:
Does the destructor function called right before or after termination of a thread?
The reason why main thread didn't print the info, is it due to the main thread already destroyed?
tsd_test.c
// test of thread-specific data
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
static pthread_once_t once = PTHREAD_ONCE_INIT;
static pthread_key_t tidKey;
static void destructor(void *buf) {
unsigned long *_tid = buf;
printf("destroy, tid: %lu\n", *_tid);
free(buf);
}
static void createKey(void) {
int s = pthread_key_create(&tidKey, destructor);
if(s != 0) {
printf("failed to create key\n");
exit(-1);
}
}
void *store_tid() {
int s;
unsigned long *buf;
// create key
s = pthread_once(&once, createKey);
if(s != 0) {
printf("failed to create key\n");
exit(-1);
}
buf = pthread_getspecific(tidKey);
if(buf == NULL) { // thread call this function for the first time,
buf = malloc(sizeof(unsigned long));
if(buf == NULL) {
printf("failed to allocate memory, %s\n", strerror(errno));
exit(-1);
}
// register buffer to specified key & current thread,
s = pthread_setspecific(tidKey, buf);
if(s != 0) {
printf("failed to setspecific\n");
exit(-1);
}
}
// store tid to buffer,
*buf = (unsigned long)pthread_self();
printf("set tid to: %lu\n", *buf);
return buf;
}
void tsd_test() {
unsigned long *tidp_a = store_tid();
printf("tid - before call another thread: %lu\n", *tidp_a);
int s;
pthread_t t2;
s = pthread_create(&t2, NULL, &store_tid, NULL);
if(s != 0) {
printf("failed to create thread\n");
exit(-1);
}
s = pthread_join(t2, NULL);
if(s != 0) {
printf("failed to join thread\n");
exit(-1);
}
printf("tid - after call another thread: %lu\n", *tidp_a);
}
int main(int argc, char *argv[]) {
tsd_test();
return 0;
}
Compile:
gcc -pthread tsd_test.c
Output:
set tid to: 3076318976
tid - before call another thread: 3076318976
set tid to: 3076315968
destroy, tid: 3076315968
tid - after call another thread: 3076318976
You can see that only the sub thread print "destroy", while the main thread didn't.
The thread destructor is called when the thread exits, not when the process dies i.e. when main() exits, the entire process dies. So destructor will not be called on that.
Call pthread_exit(NULL); either at the end of main() function or at the end tst() function (both are same really). Now, you will see the destructor being called.

Consumer Producer issue in c

Hey so I'm doing a simple producer problem but for some reason my producer runs through and then my consumer runs, even though my producer should be stopped once it can't get the semaphore initialized to 15:
#define _REENTRANT
#define BUFFER_SIZE 15
#define SHMKEY ((key_t) 7890)
//The buffer should be treated as circular buffer
#define BUFFER_WRAP(x) x%BUFFER_SIZE
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <semaphore.h>
#include <stdbool.h>
//headers
void* producerFunc(void *);
void* consumerFunc(void *);
//Structures
typedef struct
{
char* value;
} shared_mem;
typedef struct
{
int value;
} shared_dat;
//You will require 3 semaphores;
sem_t empty;
sem_t full;
sem_t crit_sec;
int start = 0;
int end = 0;
shared_mem *buffer;
//while(fscanf(fp,"%c",&newChar) != EOF)
char newChar;
FILE* fp;
shared_dat *counter;
//To compile program use the command:
//gcc name_of_program.c -lpthread -lrt
int main(void){
fp = fopen("mytest.dat", "r");
/******************init everything: threads, sems, shmem**********/
int r=0;
int i;
int shmid; /* shared memory ID */
pthread_t producer[1]; /* process id for thread 1 */
pthread_t consumer[1]; /* process id for thread 2 */
pthread_attr_t attr; /* attribute pointer array */
int status;
char *shmadd;
shmadd = (char *) 0;
int value, value1;
//create shared memory seg, if return -1 then print error
if ((shmid = shmget (SHMKEY, sizeof(int), IPC_CREAT | 0666)) < 0){
perror ("shmget");
exit (1);
}
//connect process to shared memory segment. If return is -1 then print error
if ((buffer = (shared_mem *) shmat (shmid, shmadd, 0)) == (shared_mem *) -1){
perror ("shmat");
exit (0);
}
//set the
char buffer_array[15];
buffer->value = buffer_array;
counter = (shared_dat *) malloc(sizeof(shared_dat));
/* initialize shared memory to 0 */
counter->value = 0 ;
sem_init(&empty,0,BUFFER_SIZE);
sem_init(&full,0,0);
sem_init(&crit_sec,0,1);
printf("1 - I am here %d in pid %d\n",r,getpid());
fflush(stdout);
/* Required to schedule thread independently.
Otherwise use NULL in place of attr. */
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); /* system-wide contention */
/* end to schedule thread independently */
/* Create the threads */
pthread_create(&producer[0], &attr, producerFunc, NULL);
pthread_create(&consumer[0], &attr, consumerFunc, NULL);
/* Wait for the threads to finish */
pthread_join(producer[0], NULL);
pthread_join(consumer[0], NULL);
/***************once threads finished and * reached in buffer************/
printf("from parent counter = %d\n", counter->value);
printf("---------------------------------------------------------------------------\n");
printf("\t\t End of simulation\n");
sem_destroy(&empty);
sem_destroy(&full);
sem_destroy(&crit_sec);
//release shared mem with IPC_RMID and print "end"
if ((shmctl (shmid, IPC_RMID, (struct shmid_ds *) 0)) == -1){
perror ("shmctl");
exit (-1);
}
fclose(fp);
exit(0);
}
void* producerFunc(void *arg){
bool finished = false;
while(!finished){
sem_wait(&empty);
sem_wait(&crit_sec);
end++;
if(fscanf(fp,"%c",&newChar) != EOF){
buffer->value[BUFFER_WRAP(end)] = newChar;
printf("%c",newChar);
}else{buffer->value[BUFFER_WRAP(end)] = '*';
finished = true;
}
sem_post(&crit_sec);
sem_post(&full);
}
}
void* consumerFunc(void *arg){
bool finished = false;
char val;
while(!finished){
sem_wait(&full);
sem_wait(&crit_sec);
start++;
//sleep for 1 sec
sleep(1);
if((val = buffer->value[BUFFER_WRAP(start)]) != '*'){
printf("Consuming: %c\n",val);
counter->value++;
}else{finished = true;}
sem_post(&crit_sec);
sem_post(&empty);
}
}
For some reason the producer isn't blocked after 15 letters are put into the buffer.
With consumer calling
sem_post(&empty);
you are ensuring more steps than 15 to the producer.
Also note that in your shmget() call you are assuming that
sizeof(int) >= sizeof(struct shared_mem)
which is probably correct until you don't add fields to the struct
So my solution I can't exactly explain but I compiled the code on the machines at school running windows 7. I use a mac. I know the issue was with the options I used to compile.
I needed to use the command on the school computers:
gcc -o ass3 ass3.c -lpthread -lrt
This made the semaphores work. This same command doesn't work on my mac. Apparently that -lrt option doesn't work on mac. Does anyone know why or what the equivalent is so I can get this to work on my home computer?

Pthread create as detached

I have a problem creating a thread as detached. Here's the code I wrote:
void* testFunction() {
pthread_attr_t attr;
int chk,rc;
pthread_attr_init(&attr);
printf("thread_attr_init: %d\n",rc);
pthread_attr_getdetachstate(&attr, &chk);
printf("thread_attr_getdetachedstate: %d\n",rc);
if(chk == PTHREAD_CREATE_DETACHED )
printf("Detached\n");
else if (chk == PTHREAD_CREATE_JOINABLE)
printf("Joinable\n");
return NULL;
}
int main (int argc, const char * argv[]) {
pthread_t thread1;
pthread_attr_t attr;
int rc;
rc = pthread_attr_init(&attr);
printf("attr_init: %d\n",rc);
rc = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
printf("attr_setdetachedstate: %d\n",rc);
rc = pthread_create(&thread1, &attr, testFunction, NULL);
printf("attr_create: %d\n",rc);
sleep(4);
pthread_cancel(thread1);
return 0;
}
The problem is that testFunction() always print "Joinable". Can anyone tell me where I'm getting wrong?
Try running the following code. That should clear the confusion.
/*------------------------------- join_01.c --------------------------------*
On Linux, compile with:
cc -std=c99 -pthread join_01.c -o join_01
gcc join_01.c -o join_01 -std=c99 -lpthread (Ubuntu)
Check your system documentation how to enable C99 and POSIX threads on
other Un*x systems.
Copyright Loic Domaigne.
Licensed under the Apache License, Version 2.0.
*--------------------------------------------------------------------------*/
#include <unistd.h> // sleep()
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h> // EXIT_SUCCESS
#include <string.h> // strerror()
#include <errno.h>
/***************************************************************************/
/* our macro for errors checking */
/***************************************************************************/
#define COND_CHECK(func, cond, retv, errv) \
if ( (cond) ) \
{ \
fprintf(stderr, "\n[CHECK FAILED at %s:%d]\n| %s(...)=%d (%s)\n\n",\
__FILE__,__LINE__,func,retv,strerror(errv)); \
exit(EXIT_FAILURE); \
}
#define ErrnoCheck(func,cond,retv) COND_CHECK(func, cond, retv, errno)
#define PthreadCheck(func,rc) COND_CHECK(func,(rc!=0), rc, rc)
/*****************************************************************************/
/* thread- dummy thread */
/*****************************************************************************/
void*
thread(void* ignore)
{
sleep(1);
return NULL;
}
/*****************************************************************************/
/* detach_state. Print detachstate of a thread. */
/*****************************************************************************/
/*
* We find out indirectly if a thread is detached using pthread_join().
* If a thread is detached, then pthread_join() fails with EINVAL.
* Otherwise the thread is joined, and hence was joinable.
*
*/
void
detach_state(
pthread_t tid, // thread to check detach status
const char *tname // thread name
)
{
int rc; // return code
rc = pthread_join(tid, NULL);
if ( rc==EINVAL )
{
printf("%s is detached\n", tname);
}
else if ( rc==0 )
{
printf("%s was joinable\n", tname);
}
else
{
printf("%s: pthread_join() = %d (%s)\n",
tname, rc, strerror(rc)
);
}
}
/*****************************************************************************/
/* main- main thread */
/*****************************************************************************/
int
main()
{
pthread_t tid1, tid2, tid3; // thread 1,2 and 3.
pthread_attr_t attr; // thread's attribute
int rc; // return code
/*--------------------------------------------------------*/
/* 1st test: normal thread creation */
/*--------------------------------------------------------*/
rc = pthread_create(&tid1, NULL, thread, NULL);
PthreadCheck("pthread_create", rc);
detach_state(tid1, "thread1"); // expect: joinable
/*--------------------------------------------------------*/
/* 2nd test: detach thread from main thread */
/*--------------------------------------------------------*/
rc = pthread_create(&tid2, NULL, thread, NULL);
PthreadCheck("pthread_create", rc);
rc = pthread_detach(tid2);
PthreadCheck("pthread_detach", rc);
detach_state(tid2, "thread2"); // expect: detached
/*--------------------------------------------------------*/
/* 3rd test: create detached thread */
/*--------------------------------------------------------*/
// set detachstate attribute to DETACHED
//
rc=pthread_attr_init(&attr);
PthreadCheck("pthread_attr_init", rc);
rc=pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
PthreadCheck("pthread_attr_setdetachstate", rc);
// create thread now
//
rc = pthread_create(&tid3, &attr, thread, NULL);
PthreadCheck("pthread_create", rc);
detach_state(tid3, "thread3");
/*--------------------------------------------------------*/
/* that's all folks! */
/*--------------------------------------------------------*/
return EXIT_SUCCESS;
}
The output should be
$ ./join_01
thread1 was joinable
thread2 is detached
thread3 is detached
Your testFunction is not examining anything about the current thread, rather just the initially-detached flag of a completely new attribute object you just created. Moreover, it is completely impossible, in the POSIX threads API, to recover the attributes a thread was created with or determine if a thread is detached or not. You simply have to trust that the implementation behaves as required, just like you have to trust that, if malloc(100) returns a non-null pointer, it points to a location at which you can store at least 100 bytes. This is the nature of C.
Your testFunction is not reading the current thread's attributes. Instead of calling pthread_attr_init(), pthread_getattr_np() might help you if it's present on your system, but you will need to pass the pthread_t for the thread in question onto wherever it's being queried from.

Resources