How to pass multiple values through command line arguments in void function? - c

#define SMALL_STACK 131072 //128K for stack
pthread_attr_t thread_attr; //for attr
void* fn(void* arg)
{ //fn fuction
printf("%d", (char *) arg);
return NULL;
}
int main(int argc, char** argv)
{
printf("Have ");
printf(" arguments:"); //checking multiple arguments
for (int i = 0; i < argc; ++i)
{
printf("%s", argv[i]);
}
printf("\n");
pthread_attr_init(&thread_attr);
pthread_attr_setstacksize(&thread_attr, SMALL_STACK);
pthread_t th; //creating thread and stack
/* I Need Help (void*)&argv[1] passing this to void *fn function printing the argument coming from command line arguments */
pthread_create(&th, &thread_attr, fn, (void*) &argv[1]); //creating thread
return 0;
}

In my opinion, you should pass a struct instance to your thread parameter.
Below, an example:
struct MyThreadData
{
int argc,
char** argv;
}
void* fn(void* arg)
{
MyThreadData* data=(MyThreadData*)arg;
/*code*/
return NULL;
}
int main(int argc, char** argv)
{
/*...*/
MyThreadData td={0};
td.argc=argc;
td.argv=argv;
void* ret = NULL;
pthread_create(&th, &thread_attr, fn, (void*)&td);
pthread_join(th,&ret)
}

To pass one argument (here: the 1st) change
pthread_create(&th, &thread_attr, fn, (void*)&argv[1]);
to be
pthread_create(&th, &thread_attr, fn, argv[1]);
To inside the thread function print the string use the correct conversion specifier:
printf("%s", (char *)arg);
or in a "cleaner" manner do
void* fn(void* arg)
{
char * pc = arg;
printf("%s\n", pc); /* add a new-line to flush stdout, to
have this printed immediately. */
To pass all arguments then change
pthread_create(&th, &thread_attr, fn, (void*)&argv[1]);
to be
pthread_create(&th, &thread_attr, fn, argv);
and adjust the thread function as follows:
void* fn(void* arg)
{
char ** ppc = arg;
while (*ppc)
{
printf("%s\n", *ppc);
++ppc;
}
...
Also make sure main() does not return the standard way, as this then ends the process, which in turn ends all threads of the process.
To do so replace
return 0;
by
pthread_exit(NULL);

Related

simple pthread C program - Synchronization question

I got this simple C program that uses pthreads.
I basically want to call my_function() once I'm 100% sure that my_thread() gets called and is executed.
I need to know how to synchronize the main() function and the my_thread() function.
Please note that the my_thread() never returns.
#include <stdio.h>
#include <pthread.h>
void my_function (void);
void* my_thread (void* arg);
int main (int argc, char* argv[])
{
int rc;
pthread_t id;
rc = pthread_create(&id, NULL, my_thread, NULL);
if (rc != 0)
{
return -10;
}
/*
* I wanna call my_function() once I'm 100% sure my_thread() gets called and being executed
*/
/*
* Synchronization code to add here:
*/
my_function();
return 0;
}
void* my_thread (void* arg)
{
/*
* This pthread never returns
*/
while (1)
{
/* stuff */
};
}
void my_function (void)
{
printf("Hello\n");
}
Thanks for your help.
Can anybody check if this solution is correct?
It works using the debugger but I would like to have a comment from experienced programmers.
#include <stdio.h>
#include <pthread.h>
void my_function (void);
void* my_thread (void* arg);
int started;
pthread_mutex_t mutex;
pthread_t id;
int main (int argc, char* argv[])
{
int rc;
int done;
started = 0;
mutex = PTHREAD_MUTEX_INITIALIZER;
rc = pthread_create(&id, NULL, my_thread, NULL);
if (rc != 0)
{
return -10;
}
/*
* Synchronization code proposed:
*/
done = 0;
do
{
pthread_mutex_lock(&mutex);
if (started == 1)
{
done = 1;
}
pthread_mutex_unlock(&mutex);
}
while (done == 0);
/*
* I wanna call my_function() once I'm 100% sure
* that my_thread() is called and being executed
*/
my_function();
return 0;
}
void* my_thread (void* arg)
{
started = 1;
while (1)
{
/* stuff */
};
}
void my_function (void)
{
printf("Hello\n");
}

how to pass a variable via exec*

I want to pass a int variable to another process after exec*
here is my code:
typedef union{
int i;
char c[4];
}t_t;
/* parent */
int main(int ac, char *av[])
{
t_t tv;
tv.i = 12345;
if(fork() == 0)
execlp("./test", tv.c, "abcd", (char *)0);
return 0;
}
/* child */
int main(int ac, char *av[])
{
t_t tv;
memcpy(tv.c, av[0], sizeof(int));
printf("child: ac=%d, av0: %d, av1: %s\n", ac, tv.i, av[1]);
return 0;
}
here is output:
child: ac=2, av0: 1627402297, av1: abcd
I also try like this:
int i;
execlp("./test", (char *)i, "abcd", (char *)0);
the argv[0] in the child is unexpected always.
I wonder why it can't work like I expected.
The union isn't converting the number to its string representation as you seem to expect. What it's actually doing is allowing access to the individual bytes that make up the int, which is not a string. Passing a character array that is not a string to a function expecting a string invokes undefined behavior.
What you want instead is to use snprintf to convert the integer to a string and pass that string to execlp. Then in the child process, use atoi to convert the string back to an integer.
/* parent */
int main(int argc, char *argv[])
{
char str[50];
snprintf(str, sizeof(str), "%d", 12345);
if(fork() == 0)
execlp("./test", str, "abcd", (char *)0);
return 0;
}
/* child */
int main(int argc, char *argv[])
{
int i = atoi(argv[0]);
printf("child: argc=%d, argv0: %d, argv1: %s\n", argc, i, argv[1]);
return 0;
}

passing pointer to function in pthread_create

I am trying to create a thread by passing a function pointer, however at this line
pthread_t start_thread(void *func, thread_data *tdata)
It gives me --
use-hello.c:23: error: invalid conversion from 'void*' to 'void* (*)(void*)
Any inputs please...
typedef struct thread_data{
int fd;
int threadId;
}thread_data;
pthread_t start_thread(void *func, thread_data *tdata)
{
pthread_t thread_id;
int rc;
printf("In main: creating thread\n");
rc = pthread_create(&thread_id, NULL, func, tdata);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
return(thread_id);
}
void thread_function1(thread_data *tdata){
.
.
}
int main(int argc, char **argv){
/* Our file descriptor */
int fd;
int rc = 0;
printf("%s: entered\n", argv[0]);
/* Open the device */
fd = open("/dev/hello1", O_RDWR);
if ( fd == -1 ) {
perror("open failed");
rc = fd;
exit(-1);
}
printf("%s: open: successful, fd=%d\n", argv[0], fd);
//array of function pointers
void (*function[5])(thread_data*);
function[0] = thread_function0;
function[1] = thread_function1;
function[2] = thread_function2;
function[3] = thread_function3;
function[4] = thread_function4;
//start threads
for(int i=0; i<2; i++){
thread_data *tdata[i] = (thread_data*)malloc(sizeof(thread_data));
tdata[i]->threadId = i;
tdata[i]->fd = fd;
printf("starting thread = %d\n",start_thread(function[i]), tdata[i]));
}
while(1) sleep(1); // infinite loop
printf("closing file descriptor..\n");
close(fd);
printf("file descriptor closed..\n");
return 0;
}
The problem is your declaration of start_thread, it takes a void* rather than a function pointer.
Change it to:
pthread_t start_thread(void *(*func) (thread_data *), thread_data *tdata);
A typedef for that function pointer type would simplify both that prototype and your array declaration.
typedef void (*thread_func)(thread_data*);
pthread_t start_thread(thread_func func, thread_data *tdata);
thread_func function[5];
Your function takes func as void*
pthread_t start_thread(void *func, thread_data *tdata)
And then you pass it to pthread_create as 3rd argument which should be void *(*) (void *)

number of arguments for a function in pthread

In hello world example of pthread it is stated:
#include <pthread.h>
#include <stdio.h>
void * print_hello(void *arg)
{
printf("Hello world!\n");
return NULL;
}
int main(int argc, char **argv)
{
pthread_t thr;
if(pthread_create(&thr, NULL, &print_hello, NULL))
{
printf("Could not create thread\n");
return -1;
}
if(pthread_join(thr, NULL))
{
printf("Could not join thread\n");
return -1;
}
return 0;
}
As you can see print_hello in pthread_create() has no argument, however in the definition, it looks like void * print_hello(void *arg)
What does that mean?
Now assume I have this implementation
void * print_hello(int a, void *);
int main(int argc, char **argv)
{
pthread_t thr;
int a = 10;
if(pthread_create(&thr, NULL, &print_hello(a), NULL))
{
printf("Could not create thread\n");
return -1;
}
....
return 0;
}
void * print_hello(int a, void *arg)
{
printf("Hello world and %d!\n", a);
return NULL;
}
Now I get this error:
too few arguments to function print_hello
So how can I fix that?
pthread passes one argument of type void * to thread function, So you can pass a pointer to any type of data that you want as fourth argument of pthread_create function, look at the example below that fixes your code.
void * print_hello(void *);
int main(int argc, char **argv)
{
pthread_t thr;
int a = 10;
if(pthread_create(&thr, NULL, &print_hello, (void *)&a))
{
printf("Could not create thread\n");
return -1;
}
....
return 0;
}
void * print_hello(void *arg)
{
int a = (int)*arg;
printf("Hello world and %d!\n", a);
return NULL;
}

How to pass char* argv[] to pthread_create?

I am trying to pass whatever arguments are passed into the MAIN thread to a "sub thread" I create with "pthread_create".
void *threadMainLoop(void *arg){
char *arguments = (char*)arg;
printf("arg 1 - %s\n", arguments[1]);
}
int main(int argc, char *argv[]){
printf("Start of program execution\n");
rc = pthread_create(&outboundThread, NULL, threadMainLoop, (void *) argv);
printf("Thread create rc: %i, %d\n", rc, outboundThread);
if(rc != 0){
printf("Thread creation failed\n");
exit(1);
}
pthread_join(outboundThread, NULL);
return 0;
}
The above code does not work, can you please show me how I can access the ARGV array like "argv[0]" etc in the thread?
The argv in main is a char**, not a char*, and so that's what you should cast it back to in threadMainLoop.
This works now...thanks Steve for the push in the write direction.....
void *threadMainLoop(void *arg){
char **arguments = (char**)arg;
printf("args[0] =%s\n", arguments[0]);
printf("args[1] =%s\n", arguments[1]);
}
int main(int argc, char *argv[]){
printf("Start of program execution\n");
rc = pthread_create(&outboundThread, NULL, threadMainLoop, (void *) argv);
printf("Thread create rc: %i, %d\n", rc, outboundThread);
if(rc != 0){
printf("Thread creation failed\n");
exit(1);
}
pthread_join(outboundThread, NULL);
return 0;
}

Resources