Run a task for N second in C - 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.

Related

How can i spawn n child processes to run concurrently, measure their execution time and prevent each one of them of exceeding a max execution time?

So my objective is to spawn n child processes and let them run concurrently(each one exec's a different program).
The tricky thing is that, for each one of them, I have to assure that they don't exceed a predetermined amount of time executing.(not globally, but relative to it's start time).
I only have a working code that spawns the processes, execs each one and then waits for all of them to finish.(based on this answer).
I've tried to use SIGALRM but I can not figure out how to set one alarm per fork so it does timeout each process relative to its start time and not based on the parent's starting time.
Regarding time measuring I'm not sure how could I get the execution time of each fork.
In a regular situation I would just get the delta of start and finishing time inside the child code, but in this case and if I'm not mistaken all of them execute something so I lose any reference of the following code.
for (int j = 0; j < prog_count; j++) {
pid_t monitor_pid = fork();
if(monitor_pid==0){
execvp(programs[j]->executable, programs[j]->exec_args);
}
}
while ((wpid = wait(&status)) > 0);
I've seen a lot of examples that spawn one child and control it's execution time with a sleeping timer process that runs in parallel, but i can't figure out how to extend that solution to my situation.
From man alarm
Application Usage
[...] A new process image created by one of the exec functions inherits the time left to an alarm signal in the old process' image.
So you can try to write something like:
#define LIMIT_TIME_SEC 10
for (int j = 0; j < prog_count; j++) {
pid_t monitor_pid = fork();
if(monitor_pid==0){
alarm(LIMIT_TIME_SEC);
execvp(programs[j]->executable, programs[j]->exec_args);
}
}
while ((wpid = wait(&status)) > 0);
In this code, the alarm function is called after the fork so it affects only the child process. When time indicated to alarm is reached, the SIGALARM is send to the process launched by exec function which will terminates it if it doesn't handle the signal.
If each sub-program has a different timeout, you can replace LIMIT_TIME_SEC by some array indexed like programs array.
If you want to know how much time took child processes to execute, you can built something like that:
record the child pid in program struct add the necessary member (pid_t pid;)
record the time at which the child has been launched, from parent, add member (time_t launch_time;)
for (int j = 0; j < prog_count; j++) {
pid_t monitor_pid = fork();
if (monitor_pid==0)
{
/** in child **/
/* set a limit time of execution */
alarm(LIMIT_TIME_SEC);
/* execute the program */
execvp(programs[j]->executable, programs[j]->exec_args);
}
else
{
/** in parent **/
/* record the starting time */
programs[j]->launch_time = time(NULL);
/* record the pid */
programs[j]->pid = monitor_pid;
}
}
while ((wpid = wait(&status)) > 0)
{
/* a child terminates, let's find it */
for (int j = 0; j < prog_count; ++tj)
{
if (programs[j]->pid == wpid)
{
/* print process information */
printf("program %s terminated in %df seconds\n",
programs[j]->executable,
difftime(time(NULL) - programs[j]->launch_time));
/* process found, not necessary to go further */
break;
}
}
}

C How to share informations between processes?

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.

C: Pause system() call

I got a problem in C when I try to pause an execution of a system() call.
A thread calls some application (e.g. some benchmark) repeatedly. Whenever it gets a signal SIGUSR1, the execution shall be paused and resumed on receiving SIGUSR2.
The source looks like this:
#include <signal.h>
#include <pthread.h>
void* run_app(sigset_t* signalsBetweenControllerandLoad)
{
/* assign handler */
signal(SIGUSR1, pausesignal_handler)
signal(SIGUSR2, pausesignal_handler)
pthread_sigmask(SIG_UNBLOCK, signalsBetweenControllerandLoad, NULL))
/* call application repeatedly */
while(1) {
system(SOMECOMMAND);
}
return(0);
}
static void pausesignal_handler(int signo)
{
int caughtSignal;
caughtSignal = 0;
/* when SIGUSR1 is received, wait until SIGUSR2 to continue execution */
if (signo == SIGUSR1) {
signal(signo, pausesignal_handler);
while (caughtSignal != SIGUSR2) {
sigwait (signalsBetweenControllerandLoad, &caughtSignal);
}
}
}
When I use some commands (e.g. a for loop as below that makes some computations) instead of system(SOMECOMMAND) this code works. But a program called by system() is not paused when the handler is active.
int i;
for(i=0;i<10;i++) {
sleep(1);
printf("Just a text");
}
Is there a way to pause the execution of the system() command by using thread signals? And is there even a way to stop the application called by system without needing to wait until the program is finished?
Thank you very much in advance!
system runs the command in a separate process, which doesn't even share address space with the invoking program, never mind signal handlers. The process which called system is sitting in a waitpid (or equivalent), so pausing and unpausing it will have little effect (except that if it is paused, it won't return to the loop to call system again.)
In short, there is no way to use signals sent to the parent process to pause an executable being run in a child, for example with the system() call or with fork()/exec().
If the executable itself implements the feature (which is unlikely, unless you wrote it yourself), you could deliver the signal to that process, not the one which called system.
Alternatively, you could send the SIGSTOP signal to the executable's process, which will unconditionally suspend execution. To do that, you'll need to know its pid, which suggests the use of the fork()/exec()/waitpid() sequence -- a little more work than system(), but cleaner, safer, and generally more efficient -- and you'll need to deal with a couple of issues:
A process cannot block or trap SIGSTOP, but it can trap SIGCONT so the sequence is not necessarily 100% transparent.
Particular care needs to be taken if the stopped process is the terminal's controlling process, since when it is resumed with SIGCONT it will need to reacquire the terminal. Furthermore, if the application has placed the terminal in a non-standard state -- for example, by using the readline or curses libraries which typically put the terminal into raw mode and disable echoing -- then the terminal may be rendered unusable.
Your process will receive a SIGCHLD signal as a result of the child processed being stopped. So you need to handle that correctly.
I want to present you my (shortened) resulting code after the help of #rici. Again, thank you very much.
Shortly described, the code forks a new process (calling fork) and executes there a command with exec. The parent then catches user defined signals SIGNAL_PAUSE and SIGNAL_RESUME and forwards signals to the forked child accordingly. Whenever the command finishes - catched by waitpid - the parent forks again and restarts the load.
This gets repeated until SIGNAL_STOP is sent where the child gets a SIGINT and gets cancelled.
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#define SIGNAL_PAUSE (SIGUSR1)
#define SIGNAL_RESUME (SIGUSR2)
#define SIGNAL_STOP (SIGSYS)
/* File scoped functions */
static void pausesignal_handler(int signo);
static void stopsignal_handler(int signo);
void send_signal_to_load_child(int signo);
/*Set file scope variables as handlers can only have signal-number as argument */
sigset_t* signalsBetweenControllerandLoad;
int restart_benchmark;
pid_t child_pid;
void* Load(char* load_arguments[MAX_NR_LOAD_ARGS], sigset_t* signalsToCatch) {
int load_ID;
pid_t p;
signalsBetweenControllerandLoad = signalsToCatch;
/* set signal handlers to catch signals from controller */
signal(SIGNAL_PAUSE, pausesignal_handler)
signal(SIGNAL_RESUME, pausesignal_handler)
signal(SIGNAL_STOP, stopsignal_handler)
pthread_sigmask(SIG_UNBLOCK, signalsBetweenControllerandLoad[load_ID], NULL)
/* Keep restarting benchmark until Stop signal was received */
restart_benchmark[load_ID] = 1;
/* execute benchmark, repeat until stop signal received */
while(restart_benchmark[load_ID])
{
if (child_pid == 0) {
if ((p = fork()) == 0) {
execv(load_arguments[0],load_arguments);
exit(0);
}
}
/* Parent process: Wait until child with benchmark finished and restart it */
if (p>0) {
child_pid = p; /* Make PID available for helper functions */
wait(child_pid); /* Wait until child finished */
child_pid = 0; /* Reset PID when benchmark finished */
}
}
return(0);
}
static void pausesignal_handler(int signo) {
static double elapsedTime;
int caughtSignal;
caughtSignal = 0;
if (signo == SIGNAL_PAUSE) {
send_signal_to_load_child(SIGSTOP);
printf("Load Paused, waiting for resume signal\n");
while (restart_benchmark == 1 && caughtSignal != SIGNAL_RESUME) {
sigwait (signalsBetweenControllerandLoad, &caughtSignal);
if (caughtSignal == SIGNAL_STOP) {
printf("Load caught stop signal when waiting for resume\n");
stopsignal_handler(caughtSignal);
} else if (caughtSignal != SIGNAL_RESUME) {
printf("Load caught signal %d which is not Resume (%d), keep waiting...\n",caughtSignal,SIGNAL_RESUME);
}
}
if (restart_benchmark[load_ID]) {
send_signal_to_load_child(SIGCONT, load_ID);
printf("Load resumed\n");
}
} else {
printf("Load caught unexpected signal %d.\n",signo);
}
/* reassign signals for compatibility reasons */
signal(SIGNAL_PAUSE, pausesignal_handler);
signal(SIGNAL_RESUME, pausesignal_handler);
}
static void stopsignal_handler(int signo) {
double elapsedTime;
signal(SIGNAL_STOP, stopsignal_handler);
if (signo == SIGNAL_STOP) {
restart_benchmark = 0;
send_signal_to_load_child(SIGINT);
printf("Load stopped.\n");
} else {
printf("catched unexpected stop-signal %d\n",signo);
}
}
void send_signal_to_load_child(int signo) {
int dest_pid;
dest_pid = child_pid;
printf("Error sending %d to Child: PID not set.\n",signo);
kill(dest_pid, signo);
}

Waiting for child process to terminate, or not - C

I'm trying to do an assignment for one of my classes and no professors/fellow classmates are getting back to me. So before you answer, please don't give me any exact answers! Only explanations!
What I have to do is write a c program (timeout.c) that takes in two command line arguments, W and T, where W is the amount of time in seconds the child process should take before exiting, and T is the amount of time the parent process should wait for the child process, before killing the child process and printing out a "Time Out" message. Basically, if W > T, there should be a timeout. Otherwise, the child should finish its work and then no timeout message is printed.
What I wanted to do was just have the parent process sleep for T seconds, and then kill the child process and print out the timeout, however printing out the timeout message would happen no in both cases. How do I check to see that the child process is terminated? I was told to use alarm() for this, however I have no idea of what use that function would serve.
Here's my code in case anyone wants to take a look:
void handler (int sig) {
return;
}
int main(int argc, char* argv[]){
if (argc != 3) {
printf ("Please enter values W and T, where W\n");
printf ("is the number of seconds the child\n");
printf ("should do work for, and T is the number\n");
printf ("of seconds the parent process should wait.\n");
printf ("-------------------------------------------\n");
printf ("./executable <W> <T>\n");
}
pid_t pid;
unsigned int work_seconds = (unsigned int) atoi(argv[1]);
unsigned int wait_seconds = (unsigned int) atoi(argv[2]);
if ((pid = fork()) == 0) {
/* child code */
sleep(work_seconds);
printf("Child done.\n");
exit(0);
}
sleep(wait_seconds);
kill(pid, SIGKILL);
printf("Time out.");
exit(0);
}
Although waitpid would get you the return status of the child, its default usage would force parent to wait until the child terminates.
But your requirement (if i understood correctly) only wants parent to wait for a certain time, alarm() can be used to do that.
Then, you should use waitpid() with a specific option that returns immediately if the child has not exited yet (study the api's parameters). So if the child didn't exit, you could kill it, else you already receive its return status.
You want the timeout program to stop more or less as soon as the command finishes, so if you say timeout -t 1000 sleep 1 the protecting program stops after about 1 second, not after 1000 seconds.
The way to do that is to set an alarm of some sort — classically, with the alarm() system call and a signal handler for SIGALRM — and then have the main process execute wait() or waitpid() so that when the child dies, it wakes up and collects the corpse. If the parent process gets the alarm signal, it can print its message and send death threats of some sort to its child. It might be sensible to try SIGTERM and/or SIGHUP before resorting to SIGKILL; the SIGTERM and SIGHUP signals give the errant child a chance to clean up whereas SIGKILL does not.
If you know how to manage signals, you could catch SIGALRM and SIGCHLD in your parent process. SIGCHLD will be raised when the client terminates, and SIGALRM when the timer expires. If the first raised signal is SIGALRM, the timeout expired, otherwise, if the first SIGNAL that the parent catches is SIGCHLD, the child has stopped before the expiration of the timeout.
wait() or waitpid() would still be necessary to collect the terminated child.

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