How to pass char* argv[] to pthread_create? - c

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;
}

Related

How to accept multiple arguments in system() in Linux

I am trying to implement a system() using fork() and execl(). I am unable to accept multiple arguments like ls -l and ps -a1. The code works for arguments like ls and ps. I am unable to do it. It is not allowed to change the arguments and return type of my_system(). I am a beginner. Thanks:)
int my_system(const char *command)
{
int ret = 0;
ret = execl("/bin/sh", "sh", "-c", command, (char *)NULL);
if (ret == -1)
error(1, 0, "error occcured in the execl() system call\n");
return 0;
}
int main(int argc, char *argv[])
{
pid_t pid;
pid_t ret;
char *command;
int ret_system;
int wstatus;
if (argc < 2)
error(1, 0, "Too few arguments\n");
printf("The number of arguments are: %d", argc);
command = argv[1];
printf("The pid of the parent-process is :%d\n", getpid());
pid = fork();
if (pid == -1) {
error(1, 0, "error in creating the sub-process\n");
} else if (pid == 0) {
printf("The pid of the child- process is :%d\n", getpid());
ret_system = my_system(command);
} else {
ret = waitpid(-1, &wstatus, 0);
printf("The pid of the child that has terminated is %d and the status of exit is %d\n", ret, wstatus);
}
return 0;
}
You need to make 3 changes :
int my_system(char *argv[])
...
ret = execvp(argv[1], &argv[1]);
...
ret_system = my_system(argv);
int my_system(const char *command)
{
int ret = 0;
ret = execl("/bin/sh", "sh", "-c", command, (char *)NULL);
if (ret == -1)
error(1, 0, "error occcured in the execl() system call\n");
return 0;
}
char *get_command(int argc, char **argv)
{
int i = 0;
static char command[size];
strcpy(command, argv[1]);
for (i = 2; i < argc; i++) {
strcat(command, " ");
strcat(command, argv[i]);
}
return command;
}
int main(int argc, char *argv[])
{
pid_t pid;
pid_t ret;
int ret_system;
int i = 0;
int wstatus;
char *command;
if (argc < 2)
error(1, 0, "Too few arguments\n");
printf("The pid of the parent-process is :%d\n", getpid());
pid = fork();
if (pid == -1) {
error(1, 0, "error in creating the sub-process\n");
} else if (pid == 0) {
printf("The pid of the child- process is :%d\n", getpid());
command = get_command(argc, argv);
ret_system = my_system(command);
} else {
ret = waitpid(-1, &wstatus, 0);
printf("The pid of the child that has terminated is %d and the status of exit is %d\n", ret, wstatus);
}
return 0;
}

POSIX threads and keys

I need to create two private keys and two threads and then I need to make these threads "exchange" keys
I already created the keys and initialized them and I can also print their value, but I do not know how to make them exchange keys. Maybe someone will tell you something. maybe for this I need to call the same thread several times, but I also don’t know how to do this. I do not ask you to give me a ready-made program, maybe just some little hint or advice
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
pthread_key_t key, key2;
void get_data()
{
int *x = (int*)pthread_getspecific(key2);
if(x == NULL)
printf("The value is NULL\n");
else
printf("Key value is %d\n", *x);
}
void get_data2()
{
int *x = (int*)pthread_getspecific(key);
if(x == NULL)
printf("The value is NULL\n");
else
printf("Key value is %d\n", *x);
}
void *func(void *data)
{
int *num;
int *x;
printf("Thread №%ld\n", pthread_self());
num = (int*)data;
get_data();
pthread_setspecific(key, (void*)num);
get_data();
}
void *func2(void *data)
{
int *num;
int *x;
printf("Thread №%ld\n", pthread_self());
num = (int*)data;
get_data2();
pthread_setspecific(key2, (void*)num);
get_data2();
}
int main()
{
int ret_code, type = 3;
pthread_t th, th2;
ret_code = pthread_key_create(&key, NULL);
if(ret_code != 0)
fprintf(stderr, "ptrhead_key_create() error %d\n", ret_code);
ret_code = pthread_key_create(&key2, NULL);
if(ret_code != 0)
fprintf(stderr, "ptrhead_key_create() error %d\n", ret_code);
printf("type: %d\n", type);
ret_code = pthread_create(&th, NULL, func, (void*)&type);
if(ret_code != 0)
fprintf(stderr, "pthread_create() error %d\n", ret_code);
sleep(1);
type = 10;
printf("type: %d\n", type);
ret_code = pthread_create(&th2, NULL, func2, (void*)&type);
if(ret_code != 0)
fprintf(stderr, "pthread_create() error %d\n", ret_code);
ret_code = pthread_join(th, NULL);
ret_code = pthread_join(th2, NULL);
}

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

#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);

Error when process run an instance of xterm with fork

I am given the task of forking n processes.
For each process, it must start an instance of /bin/xterm
I am done with the part of generating n processes and opening the xterm instance.
I got this output when I tried running the program. (Error in bold)
Number of process to open is 1.
Child (1): 3457
/bin/xterm: Xt error: Can't open display:
/bin/xterm: DISPLAY is not set
My code is below.
I tried googleing for the error but I have no luck so far.
Any solutions?
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
int num = atoi(argv[1]);
printf("Number of process to open is %d.\n", num);
int pid;
int i;
for(i = 0; i < num; i++)
{
pid = fork();
if(pid < 0) {
printf("Error");
exit(1);
} else if (pid == 0) {
printf("Child (%d): %d\n", i + 1, getpid());
char * const argv[] = {"/bin/xterm", NULL};
char * const envp[] = {NULL};
int rc = execve ("/bin/xterm", argv, envp);
exit(0);
} else {
wait(NULL);
}
}
return 0;
}
This little changed code works perfectly fine on my system:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(int argc, char *argv[])
{
int num = atoi(argv[1]);
printf("Number of process to open is %d.\n", num);
int pid;
int i;
for(i = 0; i < num; i++)
{
pid = fork();
if(pid < 0) {
printf("Error");
exit(1);
} else if (pid == 0) {
//printf("Child (%d): %d\n", i + 1, getpid());
//char * const argv[] = {"/bin/xterm", NULL};
//char * const envp[] = {NULL};
execl("/usr/bin/xterm", "/usr/bin/xterm", NULL);
//exit(0);
}else {
wait(NULL);
}
}
return 0;
}
The error was explained in the output you pasted:
/bin/xterm: DISPLAY is not set
You need to set DISPLAY appropriately. Otherwise, it will have no way to know where to put its display.
Also, did you really want to wait for each child after creating it?
Use
char *envp[] = {"TERM=vt100", "PATH=/bin:/usr/bin", "DISPLAY=:0.0",(char *) 0 };
Doing so you set the display on your machine.
Sorry I'm late.

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 *)

Resources