C How to share informations between processes? - c

I would need some help with some C code.
Basically I have n processes which execute some code. Once they're almost done, I'd like the "Manager Process" (which is the main function) to send to each of the n processes an int variable, which may be different for every process.
My idea was to signal(handler_function, SIGALRM) once all processes started. When process is almost done, it uses kill(getpid(), SIGSTOP) in order to wait for the Manager Process.
After SIM_TIME seconds passed, handler_function sends int variable on a Message Queue then uses kill(process_pid, SIGCONT) in order to wake up waiting processes. Those processes, after being woken up should receive that int variable from Message Queue, print it and simply terminate, letting Manager Process take control again.
Here's some code:
/**
* Child Process creation using fork() system call
* Parent Process allocates and initializes necessary variables in shared memory
* Child Process executes Student Process code defined in childProcess function
*/
pid_t runChild(int index, int (*func)(int index))
{
pid_t pid;
pid = fork();
if (pid == -1)
{
printf(RED "Fork ERROR!\n" RESET);
exit(EXIT_FAILURE);
}
else if (pid == 0)
{
int res = func(index);
return getpid();
}
else
{
/*INSIGNIFICANT CODE*/
currentStudent = createStudent(pid);
currentStudent->status = FREE;
students[index] = *currentStudent;
currentGroup = createGroup(index);
addMember(currentStudent, currentGroup);
currentGroup->closed = FALSE;
groups[index] = *currentGroup;
return pid;
}
}
Code executed by each Process
/**
* Student Process Code
* Each Student executes this code
*/
int childProcess(int index)
{
/*NOTICE: showing only relevant part of code*/
printf("Process Index %d has almost done, waiting for manager!\n", index);
/* PROGRAM GETS STUCK HERE!*/
kill(getpid(), SIGSTOP);
/* mex variable is already defines, it's a struct implementing Message Queue message struct*/
receiveMessage(mexId, mex, getpid());
printf(GREEN "Student %d has received variable %d\n" RESET, getpid(), mex->variable);
}
Handler Function:
* Handler function
* Will be launched when SIM_TIME is reached
*/
void end_handler(int sig)
{
if (sig == SIGALRM)
{
usleep(150000);
printf(RED "Time's UP!\n" RESET);
printGroups();
for(int i = 0; i < POP_SIZE; i++){
mex->mtype = childPids[i];
mex->variable = generateInt(18, 30);
sendMessage(mexId, mex);
//childPids is an array containing PIDs of all previously launched processes
kill(childPids[i], SIGCONT);
}
}
I hope my code is understandable.
I have an issue though, Using provided code the entire program gets stuck at kill(getpid(), SIGSTOP) system call.
I also tried to launch ps in terminal and no active processes are detected.
I think handler_function doesn't send kill(childPids[i], SIGCONT) system call for some reason.
Any idea how to solve this problem?
Thank you

You might want to start by reading the manual page for mq_overview (man mq_overview). It provides a portable and flexible communication mechanism between processes which permits sync and async mechanisms to communicate.
In your approach, there is a general problem of “how does one process know if another is waiting”. If the process hasn’t stopped itself, the SIGCONT is ignored, and when it subsequently suspends itself, nobody will continue it.
In contrast, message-based communication between the two can be viewed as a little language. For simple exchanges (such as yours), the completeness of the grammar can be readily hand checked. For more complex ones, state machines or even nested state machines can be constructed to analyze their behaviour.

Related

Background execvp : how to do it properly?

Like many others, I'm trying to simulate a shell. I've gotten to use the execvp properly on a string coming from the user. The string is parsed and an array of strings is generated (each word has its array, split on the space character), including a NULL at the very end.
When I find that the last word entered by the user is &, I set a flag up to notify my shell that the command is to be executed in the background while letting the user input another command right away. The "background-executed" command sees its & replaced by a NULL character within the array of strings passed to execvp.
As it is, I've been trying to use a pthread to run the process in the background, but it's acting somewhat weird: the command passed to execvp through the thread's function requires me to press two times ENTER after sending the command.
Here is my simplified main function that is to simulate a shell:
int main (void) {
fprintf (stdout, "%% ");
bool running = true;
while(running) {
/* Ask for an instruction and parses it. */
char** args = query_and_split_input();
/* Executing the commands. */
if (args == NULL) { // error while reading input
running = false;
} else {
printf("shell processing new command\n");
int count = count_words(args);
split_line* line = form_split_line(args, count);
Expression* ast = parse_line(line, 0, line->size - 1);
if(line->thread_flag) {
pthread_t cmd_thr;
/* Setting up the content of the thread. */
thread_data_t thr_data;
thr_data.ast = *ast;
thr_data.line = *line;
/* Executing the thread. */
int thr_err;
if ((thr_err = pthread_create(&cmd_thr, NULL, thr_func, &thr_data))) {
fprintf(stderr, "error: pthread_create, rc: %d\n", thr_err);
return EXIT_FAILURE;
}
printf("thread has been created.\n");
} else {
run_shell(args);
}
free(line);
printf("done running shell on one command\n");
}
}
/* We're all done here. See you! */
printf("Bye!\n");
exit (0);
}
Here is my thread's function:
void *thr_func(void *arg) {
thread_data_t *data = (thread_data_t *)arg;
data->line.content[data->line.size-1] = NULL; // to replace the trailing '&' from the command
run_shell(data->line.content);
printf("thread should have ran the command\n");
pthread_exit(NULL);
}
And the actual line that runs a command:
void run_shell(char** args) {
/* Forking. */
int status;
pid_t pid; /* Right here, the created THREAD somehow awaits a second 'ENTER' before going on and executing the next instruction that forks the process. This is the subject of my first question. */
pid = fork();
if (pid < 0) {
fprintf(stderr, "fork failed");
} else if (pid == 0) { // child
printf("Child executing the command.\n");
/* Executing the commands. */
execvp(args[0], args);
/* Child process failed. */
printf("execvp didn't finish properly: running exit on child process\n");
exit(-1);
} else { // back in parent
waitpid(-1, &status, 0); // wait for child to finish
if (WIFEXITED(status)) { printf("OK: Child exited with exit status %d.\n", WEXITSTATUS(status)); }
else { printf("ERROR: Child has not terminated correctly. Status is: %d\n", status); }
free(args);
printf("Terminating parent of the child.\n");
}
}
So basically, as an example, what run_shell(args) receives is either ["echo","bob","is","great",NULL] (in the case of a sequential execution) or ["echo","bob","is","great",NULL,NULL] (in the case of a command to be executed in the background).
I've left the printf traces since it might help you understand the execution flow.
If I input echo bob is great, the output (printf traces) is:
shell processing new command
Child executing the command.
bob is great
OK: Child exited with exit status 0.
Terminating parent of the child.
done running shell on one command
However, if I input echo bob is great &, the output is:
shell processing new command
thread has been created.
done running shell on one command
And then I actually need to press ENTER again to obtain the following output:
Child executing the command.
bob is great
OK: Child exited with exit status 0.
Terminating parent of the child.
thread should have ran the command
(On that last execution, I also get traces of my function that queries and parses the input of the user, but that seemed irrelevant so I abstracted this whole part.)
So my questions are:
How comes the created thread awaits a second ENTER before running the execvp ? (thr_func stops executing run_shell and awaits the second ENTER right before the pid = fork(); instruction)
Do I have the right approach to solve the problem at hand? (Trying to execute a shell command in the background.)
You cannot use a thread to simulate a process. Well, strictly you can, but there's no use on doing that. The problem is that all the threads belonging to a process share the same virtual address space. There's no reason to create a thread, as you finally need to fork() to create a new process (you'll need this for reasons explained below), so why to create two threads of execution if one of them will be stopped all the time just waiting for the subprocess to finish. There's no use on this schema.
The need of a fork() system call comes historically to make a simple call to create a new process (with different virtual memory map) to allow for a new program to be able to be executed. You need to create a new, complete process before calling exec(2) system call, because the process address space will be overwritten by the text and data segments of the new program. If you do this in a thread, you'll be overwriting the whole process address space (this is the shell) and killing all the threads you can have running on behalf of that process. The schema to follow is (pseudocode):
/* create pipes for redirection here, before fork()ing, so they are available
* in the parent process and the child process */
int fds[2];
if (pipe(fds) < 0) { /* error */
... /* do error treatment */
}
pid_t child_pid = fork();
switch(child_pid) {
case -1: /* fork failed for some reason, no subprocess created */
...
break;
case 0: /* this code is executed in the childd process, do redirections
* here on pipes acquired ***before*** the fork() call */
if (dup2(0 /* or 1, or 2... */, fds[0 /* or 1, or 2... */]) < 0) { /* error */
... /* do error management, considering you are in a different process now */
}
execvpe(argc, argv, envp);
... /* do error management, as execvpe failed (exec* is non-returning if ok) */
break; /* or exit(2) or whatever */
default: /* we are the parent, use the return value to track the child */
save_child_pid(child_pid);
... /* close the unused file descriptors */
close(fds[1 /* or 0, or 2, ... */]);
... /* more bookkeeping */
/* next depends on if you have to wait for the child or not */
wait*(...); /* wait has several flavours */
} /* switch */
Exec and fork system calls are separated by two reasons:
you need to be able to do housekeeping between both calls to execute the actual redirections in the child before exec().
there was a time when unix was not multitasking or protected, and the exec call just replaced all the memory in the system with the new program to execute (including kernel code, to cope with the fact that an unprotected system could be corrupted by the executing program) This was common in old operating systems and I've seen it on systems like CP/M or TRS-DOS. The implementation in unix conserved almost all the semantics of exec() call and added with fork() the unavailable functionality only. This was good, as it allowed both, parent and child processes to do the necessary bookkeeping when the time for pipes came.
Only if you need a different thread to communicate with each child is when you probably can use a different thread to do the task. But think that a thread shares all the virtual space with the parent (case we can talk about a parent/child relationship between threads) and if you do an exec call you'll get that virtual space overwritten for the whole process (all threads there)

Background and suspended processes - Implementing a Job Control Shell in C

I'm implementing a Job Control Shell in C in Linux as a project for a Operating Systems-related subject. I have a main() function that does child process management, helped with a linked list as shown here in which background and suspended jobs information is stored:
typedef struct job_
{
pid_t pgid; /* group id = process lider id */
char * command; /* program name */
enum job_state state;
struct job_ *next; /* next job in the list */
} job;
Every time a child process exits or is stopped, a SIGCHLD is sent to parent process to be informed about that. Then, I have a signal handler as shown here that for each node of that job status linked list, checks if the process represented in that node has exited and if it did, that node is removed from the linked list.
Here is the code for the SIGCHLD handler, where 'job_list' is the linked list where the info is stored:
void mySIGCHLD_Handler(int signum) {
block_SIGCHLD();
if (signum == 17) {
job *current_node = job_list->next, *node_to_delete = NULL;
int process_status, process_id_deleted;
while (current_node) {
/* Wait for a child process to finish.
* - WNOHANG: return immediately if the process has not exited
*/
waitpid(current_node->pgid, &process_status, WNOHANG);
if (WIFEXITED(process_status) != 0) {
node_to_delete = current_node;
current_node = current_node->next;
process_id_deleted = node_to_delete->pgid;
if (delete_job(job_list, node_to_delete)) {
printf("Process #%d deleted from job list\n", process_id_deleted);
} else {
printf("Process #%d could not be deleted from job list\n", process_id_deleted);
}
} else {
current_node = current_node->next;
}
}
}
unblock_SIGCHLD();
}
The thing is, when the handler is called, some entries that should not be deleted because the process they represent are not exited, are deleted, when they shouldn't. Anyone would know why that happens?
Thank you and sorry for your lost time :(
I see many problems in this code, but the immediate issue is probably here:
waitpid(current_node->pgid, &process_status, WNOHANG);
if (WIFEXITED(process_status) != 0) {
When waitpid(pid, &status, WNOHANG) returns because the process has not exited, it does not write anything to status, so the subsequent if is branching on garbage. You need to check the actual return value of waitpid before assuming status is meaningful.
The most important other problems are:
The kernel is allowed to send only one SIGCHLD to tell you that several processes have exited. When you get a SIGCHLD, you need to call waitpid(0, &status, WNOHANG) in a loop until it tells you there are no more processes to wait for, and you need to process (no pun intended) all of the exited process IDs that it tells you about.
It is not safe to call printf or free from an asynchronous signal handler. Add terminated processes to a list of deferred tasks, instead. Make sure to block SIGCHLD in the main-loop code that consumes that list.
Don't block and unblock SIGCHLD yourself in the handler; that has an unavoidable race condition. Instead, let the kernel do it for you, atomically, by setting up your signal handler correctly: use sigaction and don't put SA_NODEFER in sa_flags. (Do put SA_RESTART in sa_flags, unless you have a very good reason not to.)
The literal number 17 should be the signal constant SIGCHLD instead. Some signal numbers have been stable across all Unixes throughout history, but SIGCHLD is not one of them.

Run a task for N second in C

I'm trying to complete an assignment for uni and I'm encountering an issue. I want to create something like a "timer" for my program. What I mean is that I want to run the program for 30 seconds, and after those have passed I want to print some stats before closing it. Since it is a process related project I would like this timer to be passed to the child processes as well if possible. Here is some pseudo-code of what I'm trying to accomplish.
/* Timer starts from here */
- forking childs
- child execute
- other actions
/* Timer finishes here */
Printing statistics
exit(0)
I tried reading up something on alarm, time and others but I wasn't able to find anything that could help me. Hope you can help me out and thanks in advance.
Try to read the man pages of alarm(). check the man page of alarm
unsigned int alarm(unsigned int seconds);
What alarm returns ? alarm() returns the number of seconds remaining until any previously scheduled alarm was due to be delivered, or zero if there
was no previously scheduled alarm.
you can set multiple alarm() for N seconds, but not all at a time.
Here is the simple code to understand alarm().
#include<signal.h>
#include<stdio.h>
int al = 5;
void my_isr(int n)
{
static int count = 0;//count variable
if(n == 17) {
/** this child will execute if child completer before 5 seconds**/
int ret = wait(0);//releases child resources
printf("child %d completed \n",ret);
}
if(n == 14) {
printf("in sigalarm isr \n");
/** do task here **/
if(count<3) {
alarm(5);// after doing some task set another alarm
}
count++;
}
}
int main()
{
if(fork()==0)
{
printf("child : pid = %d ppid = %d\n",getpid(),getppid());
/** letting the child to run for 20 seconds **/
sleep(20);
printf("child exits after task over \n");
exit(0);
}
else
{
alarm(al);//setting 5 seconds timer for child to finish job
signal(SIGALRM,my_isr);
/** to avoid child to become zombie. when child completes parents will receive SIGCHLD signal, upon receving this parent needs to free the resources associated with it using wait */
signal(SIGCHLD,my_isr);
while(1);//to keep main process alive for observation
}
}
I hope it helps you.

Make child process wait for parent

I have to write a program in C that will fork a new process and then use that processes pid for another function. However I need to call this function before the child process can run and I don't know how to do this.
Here's some pseudo code of what I'm trying to do.
pid_t pid = fork();
if(in_child){ //In the child process
//launch child application
//somehow stop the child application before it actually executes any code
}
else{
//call my function with the child's pid
//resume the child process
//do other stuff
}
If you need any additional info please ask. Thanks.
Edit: I do not have access to the code for the child. I'm just wanting to run an executable.
If you mean any code at all, that can be difficult. You can use clone with CLONE_STOPPED instead of fork to start the application into a stopped state (needing SIGCONT to get it going again).
However, if you simply mean specific code in the child and you can modify the child code, you can, as the first thing in main, simply set up a handler for a USR1 signal (any IPC would probably do but a signal seems the simplest in this particular case) and then wait for it to fire before carrying on.
That way, the process itself will be running but won't be doing anything yet.
You then have the parent weave whatever magic it needs to do, then send a SIGUSR1 to the child.
But since, according to a comment, you don't have access to the client code, the first option may be the best, assuming that SIGCONT won't actually cause problems with the child. That will require testing.
Of course, one thing to keep in mind is that neither clone() nor fork() will actually load your new program into the child process, that has to be done with an exec-type call after the split. This is a result of the UNIX split between fork and exec functionality, detailed here.
That means that, while you don't control the child program, you do control the child process, so your code can wait for whatever signal it wants before loading up the new child program. Hence it's doable even with just fork().
Unfortunately, that also means that neither clone nor fork can stop your process after the new program has been loaded with exec (at least not deterministically) so, if the fiddling you want to do is to the new program (such as manipulating its variables by attaching to its memory), you can't do it.
The best you can do is to fiddle with the new process while it still has a copy of the old program (before the exec).
There's a simpler way, assuming your OS will let you share the address space before the child execs. Pseudo-code follows.
volatile int barrier;
int safe_fork(routine_to_call)
{
pid_t pid;
barrier = 0;
pid = fork();
if (pid == 0) {
/* parent */
routine_to_call()
barrier = 1;
} else if (pid > 0) {
while (barrier = 0)
; /* or sleep if it's a slow routine */
exec()
//if we get here, exec failed; exit with failure code
} else {
/* return failure */
}
/* must be parent; return success */
}
You may need to do something special to get the sharing behaviour, rather than having them both start with independent copies. I know it's doable on FreeBSD. In linux, check out the CLONE_VM flag to clone(); it looks like it should let you do what you need here.
What you are looking for is interprocess condition variable.
https://en.wikipedia.org/wiki/Monitor_(synchronization)
The way it would work (roughly) :-
Before forking you set a variable asking child to wait :- child_continue = false
1.) CHILD process begins to execute (or parent, doesn't matter)
If the variable child_continue == false
Sleep on a condition variable and wait for signal from parent
2.) Parent process waits for its chance to run (note the order of run doesn't matter). When the parent process is ready to run, it does whatever it wants with the child PID (or something else) and signals the child process to continue.
In order to do this, you'd need interprocess mutex and interprocess condition variable.
//#include "pthread.h" in main file
//create IPC MUTEX which can be shared by both child and parent.
pthread_mutexattr_t mutex_attr;
pthread_condattr_t cond_attr;
pthread_mutex_t mtx;
pthread_cond_t cond;
if (0!= pthread_mutexattr_init(&mutex_attr))
{
//errror handling
}
if (0!= pthread_condattr_init(&cond_attr))
{
//errror handling
}
if (0 != pthread_condattr_setpshared(&cond_attr,PTHREAD_PROCESS_SHARED)
{
//error handling
}
if (0 != pthread_mutexattr_setpshared(&mutex_attr,PTHREAD_PROCESS_SHARED)
{
//error handling
}
if (0 !=pthread_mutex_init(&mtx,&mtx_attr))
{
//error handling
}
if (0 !=pthread_cond_init(&cond,&cond_attr))
{
//error handling
}
boolean child_continue = false;
//now fork !!
pid_t pi = fork();
if (pi ==0) //child
{
if (0 !=pthread_mutex_lock(&mtx))
{
//error handling
}
while (!child_continue) //wait until we receive signal from parent.
{
if (0 !=pthread_cond_wait(&cond,&mtx))
{
//error handling
}
}
if (0 !=pthread_mutex_unlock(&mtx))
{
//error handling
}
//Parent is done!! either we woke up by condition variable or, parent was done before hand
//in which case, child_continue was true already.
}
else
{
//in parent process do whatever you want with child pid (pi variable)
//once you are done, set child_continue to true and wake up child.
if (0 !=pthread_mutex_lock(&mtx))
{
//error handling
}
child_continue = true;
if (0 !=pthread_cond_signal(&cond))
{
//error handling
}
if (0 !=pthread_mutex_unlock(&mtx))
{
//error handling
}
}

C programming. Using execl and pthread

I'm having a problem in the combined use of execl() and pthread.
My idea is quite simple: write a daemon that in certain situation starts an external process (a separate executable with respect to the daemon itself) and wait for the return value of that process. Moreover I want to have the possibility to start multiple instances of the same process at the same time.
The part of my code to handle multiple threads:
...
for (c_thread=0,i=0;i<N;i++)
{
/* Start actions before start threads */
for (j=c_thread;j<c_thread+config.max_threads;j++)
Before_Process(act[act_index[j]].measID);
/* Now create threads */
for (c=0,j=c_thread;j<c_thread+config.max_threads;j++)
{
Print_Log(LOG_DEBUG,"Create tread n. %d, measurementID=%s",c,act[act_index[j]].measID);
if ((ret=pthread_create(&pth[c],NULL,Start_Process_Thread,(void *) &act[act_index[j]].measID)))
{
Print_Log(LOG_ERR,"Error in creating thread (errorcode: %d)",ret);
exit(EXIT_FAILURE);
}
c++;
}
/* Joint threads */
for (j=0;j<config.max_threads;j++)
{
if ((ret=pthread_join(pth[j], (void**) &r_value[j])))
{
Print_Log(LOG_ERR,"Error in joint thread (errorcode: %d)",ret);
exit(EXIT_FAILURE);
}
}
/* Perform actions after the thread */
for (j=0;j<config.max_threads;j++)
{
status=*(int*) r_value[j];
Print_Log(LOG_DEBUG,"Joint tread n. %d. Return value=%d",j,status);
After_Process(act[act_index[c_thread+j]].measID,status);
}
c_thread += config.max_threads;
}
...
And the function Start_Process_Thread:
void *Start_Process_Thread(void *arg)
{
int *ret;
char *measID;
measID=(char*)arg;
if (!(ret=malloc(sizeof(int))))
{
Print_Log(LOG_ERR, "allocation memory failed, code=%d (%s)",
errno, strerror(errno) );
exit(EXIT_FAILURE);
}
*ret=Start_Process(measID);
pthread_exit(ret);
}
int Start_Process(char *measID)
{
...
pipe(pfd);
pid=fork();
if (!pid)
{
signal(SIGALRM,Timeout);
alarm(config.timeout_process);
flag=0;
/*
Start the Process.
*/
ret=execl(config.pre_processor,buff_list[TokCount-1],config.db_name,measID,(char *) 0);
if (ret==-1)
{
alarm(0);
flag=1;
Print_Log(LOG_ERR,"Cannot run script %s, code=%d (%s)",config.process, errno, strerror(errno));
}
alarm(0);
close(1);
close(pfd[0]);
dup2(pfd[1],1);
write(1,&flag,sizeof(int));
}
else
{
wait(&status);
close(pfd[1]);
read(pfd[0],&flag,sizeof(int));
close(pfd[0]);
if (!flag)
{
if (WIFEXITED(status))
{
if (!(return_value=WEXITSTATUS(status)))
{
/*
Process gives no errors.
*/
Print_Log(LOG_INFO, "Processing of measurementID=%s ended succesfully!",measID);
}
else
{
/*
Process gives errors.
*/
Print_Log(LOG_WARNING,"Processor failed for measurementID=%s, code=%d",measID, return_value);
}
}
else
{
/*
Timeout for Process
*/
Print_Log( LOG_WARNING,"Timeout occurred in processing measurementID=%s",measID);
return_value=255;
}
}
}
}
The above code works fine from technical point of view but I have a problem somewhere in handling the return values of the different instances of the called external process. In particular it happens that the return value associated to a certain instance is attributed to a different one randomly.
For example suppose 4 different instances of the external process are called with the arguments meas1, meas2, meas3 and meas4 respectively and suppose that meas1, meas2 and meas3 are successfully processed and that for meas4 the process fails. In situation like that my code mix up the return vales giving success for meas1, meas3, and meas4 and failure for meas2 or success for meas1, meas2, meas4 and failure for meas3.
Any idea on why this can happens?
Any help is really welcome.
Thank you in advance for your attention.
When any thread in a process executes wait(), it gets the information about any of the process's dead children — not necessarily about the last child started by the thread that is doing the waiting.
You are going to need to think about:
Capturing the PID of the process that died (it is returned by wait(), but you ignore that).
Having a single thread designated as the 'disposer of corpses' (a thread that does nothing but wait() and record and report on deaths in the family of child processes).
A data structure that allows the threads that start processes to record that they are interested in the status of the child when it dies. Presumably, the child should wait on a suitable condition once a child starts so that it is not consuming CPU time doing nothing useful.
The 'disposer of corpses' thread handles notifications of the appropriate other thread whenever it collects a corpse.
Worry about timeouts on the processes, and killing children who run wild for too long.
It's a morbid business at times...

Resources