I would like to limit the execution of a function in pure C, without stopping the whole program.
I believe the closest thing on stackoverflow.com to this was on the last comment of this thread: How to limit the execution time of a function in C/POSIX?
There was some talk of using setjmp and longjm placed after the function to limit in time, but the thread died.
Is there anyone that knows if this is indeed possible?
Cheers
I can see two options, first one check the time every few lines of code and return if it's too much, but I don't think it's a good idea.
Second, you could use threads. Run two functions at the same time, one timing the other, if the time is too big then it kills the first one. Now I'm pretty sure that windows and Linux have different libraries to create threads so you could try and use a library that works across all platforms like this one maybe http://openmp.org/wp/.
I'm not too familiar with that library and threads in general but I hope it helps
Though it could be of service to post my solution. It is a combination of this post http://cboard.cprogramming.com/c-programming/148363-limit-execution-time-function.html, and the IPC TPL example found here: https://github.com/troydhanson/tpl/blob/master/doc/examples.txt.
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <stdbool.h>
#include <string.h>
#include "tpl.h"
//This example contains two different parts:
//1) The alarm is a execution timer for the function doWork
//2) There is a need, that if the execution exits correctly, that the chid value of i, that we are modifying be passes
typedef struct TEST_STRUCT
{
int i;
double sum;
} testStruct;
int doWork(testStruct * ts)
{
int y;
for(y=0; y<3; y++)
{
sleep(1);
printf("Working: %d\n", ts->i);
ts->i++;
ts->sum += (double)ts->i;
}
return 0;
}
int main()
{
testStruct * ts = (testStruct *)(calloc(1, sizeof(testStruct)));
ts->i = 7;
ts->sum = 4.0;
tpl_node *tn;
int fd[2];
pipe(fd);
int y;
for(y=0; y<10; y++)
{
pid_t childPID = fork();
if (childPID==0)
{
unsigned secsLeft;
alarm(10);
doWork(ts);
printf("\t->%d\n", ts->i);
printf("\t->%p\n", (void*) &ts->i);
tn = tpl_map("S(if)", ts);
tpl_pack( tn, 0 );
tpl_dump( tn, TPL_FD, fd[1]);
tpl_free( tn );
secsLeft = alarm(0);
exit(0);
}
else
{
//IMPORTANT TO PUT IT HERE: In case the buffer is too big, TPL_DUMP will wait until it can send another and hang
tn = tpl_map( "S(if)", ts );
tpl_load( tn, TPL_FD, fd[0]);
int status;
wait(&status);
if(WIFSIGNALED(status))
{
// child was interrupted
if (WTERMSIG(status) == SIGALRM)
{
printf("Interrupted\n");
// child interrupted by alarm signal
}
else
{
printf("Should not happend\n");
// child interrupted by another signal
}
}
else
{
tpl_unpack(tn,0);
tpl_free( tn );
printf("\t->%d\n", ts->i);
printf("\t->%p\n", (void*) &ts->i);
printf("Success\n");
}
}
}
return 0;
}
Basically, we fork the program, where the child performs a task and the parent waits for the child to finish. The child contains an alarm, that if true signals the parent that it existed in that manner. If it completes (as this example shows), the child sends the object function to the parent as a TPL buffer.
Related
Introduction
I have a program where child threads are created that I would like to profile with Valgrind memcheck. From the responses to a previous question I've asked, I will need to use joinable (rather than detached) threads in order to test and profile reliably with Valgrind memcheck.
Stack vs. Heap Allocation
My program is sufficiently large where I don't think I can create the thread and join it in the same scope. For this reason I allocate space for the pthread_t on the heap.
Attempt #1 - Joining Immediately
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <stdint.h>
void my_thread() {
printf("I'm in a child thread!\n");
pthread_exit(NULL);
}
pthread_t* const make_thread() {
pthread* const thread = malloc(sizeof(pthread_t));
pthread_create(thread, NULL, (void*) &my_thread, NULL));
return thread;
}
int main() {
printf("Hello, world!\n");
uint8_t i;
for(i = 0; i < 255; ++i) {
pthread_t* const thread_handle = make_thread();
pthread_join(*thread_handle, NULL);
free(thread_handle);
}
return 0;
}
This seems to make sense, but now I want to extend this example by not joining the thread immediately, and only joining on program exit (say, because these threads may become long-living). IOW the above example kind of defeats the purpose of multithreading.
I want to create threads and only really ever force a join on program exit.
Attempt #2 - Joining at the end
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <stdint.h>
#include <glib-2.0/glib.h>
#include <unistd.h>
void my_thread() {
sleep(3);
printf("I'm in a child thread!\n");
pthread_exit(NULL);
}
pthread_t* const make_thread() {
pthread* const thread = malloc(sizeof(pthread_t));
pthread_create(thread, NULL, (void*) &my_thread, NULL));
return thread;
}
int main() {
printf("Hello, world!\n");
GArray* const thread_handles = g_array_new(TRUE, TRUE, sizeof(pthread*));
// Important loop
uint8_t i;
for(i = 0; i < 255; ++i) {
pthread_t* const thread_handle = make_thread();
g_array_append_val(thread_handles, thread_handle);
}
for(i = 0; i < thread_handles->len; ++i) {
pthread_t* const thread_handle =
g_array_index(thread_handles, pthread*, i);
pthread_join(*thread_handle, NULL);
free(thread_handle);
}
g_array_free(thread_handles, TRUE);
return 0;
}
This is cool but what if "Important loop" is actually endless? How can I prevent thread_handles from expanding until it takes up all available memory?
In the actual program (these are just minimal examples), the program receives network messages and then kicks off threads for some special types on network messages.
So, what is your real issue?
For normal network servers, etc, the usual is to combine both of your approaches.
The main thread has a two nested loops that:
waits for a connection/message.
Creates a thread.
Adds this to the list of active threads.
Loops on all active threads in the list (as below)
Loop on the active thread list:
look for a thread that is marked "done"
Remove it from the list
join it
free the thread struct
The above works pretty much the same if the thread control structs are allocated (via malloc) or come from a fixed, pre-defined array of structs [which can be function scoped to main or global/static scope].
Here's some C-like pseudo code to illustrate:
// task control
typedef struct tsk {
pthread_t tsk_tid; // thread id
int tsk_sock; // socket/message struct/whatever
int tsk_isdone; // 1=done
} tsk_t;
void
my_thread(tsk_t *tsk)
{
// do stuff ...
// tell main we're done
tsk->tsk_isdone = 1;
return (void *) 0;
}
void
main_loop(void)
{
while (1) {
// wait for connection, message, whatever ...
int sock = accept();
// create thread to handle request
tsk_t *tsk = make_thread(sock);
// enqueue it to list of active threads
list_enqueue(active_list,tsk);
// join all completed threads
while (1) {
int doneflg = 0;
// look for completed threads
for_all(tsk,active_list) {
if (! tsk->tsk_isdone)
continue;
// remove task from queue/list
list_remove(active_list,tsk);
// join the thread
pthread_join(tsk->tsk_tid,NULL)
// release storage
free(tsk);
// say we reaped/joined at least one thread
doneflg = 1;
}
// stop when we've joined as many threads as we can
if (! doneflg)
break;
}
}
}
Note that while creating a new thread for a new connection may be reasonable, doing so for messages from a given connection can be very slow.
It may be better to have a pool of worker threads. See my answer: Relative merits between one thread per client and queuing thread models for a threaded server?
I have this code:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
int cpt = 0;
void handler (int sig) {
cpt++ ;
}
int main() {
int i;
signal(SIGCHLD, handler);
for (i = 0; i < 5; i++) {
if (fork() == 0) {
exit(0);
}
}
while (wait(NULL) != -1) ;
printf("cpt = %d\n", cpt);
return 0;
}
this program to my understanding should always print cpt = 5
but when i run it on my machine it returns different values (3,4,5) why is that?
The SIGCHLD signal is a little funny and doesn't work like you'd expect: we think we should get one signal per child death, but that's not it.
Instead, it's a kind of level-triggered thing where at some unknown intervals it sends the signal if there are any un-waited-for children.
In the loop you provided that burns through the wait(), this loop is consuming multiple children before the signal handler gets around to it, hence less trips through the handler.
Others have pointed out that you should be using a volatile sig_atomic_t variable, and though this is a good idea, it's not why you're seeing this behavior.
I believe the only way to get a guaranteed one-signal-per-child is to actually wait for the child in the signal handler - this makes it appear more like an edge-triggered signal.
Of course, you're pretty limited to what you can do in the signal handler, so if your application already has a good regimen for waiting for child processes, you likely don't need a SIGCHLD handler.
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
static volatile sig_atomic_t cpt = 0;
static void handler(int sig) {
cpt++;
wait(NULL); // ADD ME
}
int main() {
int i;
signal(SIGCHLD, handler);
for (i = 0; i < 5; i++) {
if (fork() == 0) {
exit(0);
}
}
while (wait(NULL) != -1) ;
printf("cpt=%d\n", cpt);
return 0;
}
As an alternative, if the while() loop were not so tight and had other processing (or even an explicit delay), there would not be a race condition and you'd see all five SIGCHLD delivered.
I am trying to develop a simple railroad simulation following the answer to the question Make children process wait until receiving parent's signal.
My task: I have exactly 5 process representing trains. I need to create these 5 process (T1, T2, T3, T4, and T5) via fork(), and pause each one until all of them are created. After that the parent process will send a signal to the children, and each child will use an execl (i.e. execl(execl_path_name, CHILDETCONE, i, NULL);). After signaling, the parent waits for all the children to complete their tasks.
I quite understand the handler function, but I am not clear on these points:
Do I need to insert my execl inside the handler function?
I don't understand the significance of this last loop from the answer to the previous question:
for (int i = 0; i < NUMBER_TRAINS; i++)
{
wait(NULL);
}
This is my code:
#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include "accessory.h"
#define NUMBER_TRACKS 16
#define NUMBER_STATIONS 8
#define NUMBER_TRAINS 5
#define TRACKS_INITIALS "MA"
#define STATION_INITIALS "S"
#define SIZE 256
#define CHILDETCONE "childETCone"
void handler(int sig);
int main(int argc , char *argv[]) {
pid_t pid;
pid_t pid_array[NUMBER_TRAINS];
char track_name[2];
char track_number[2];
int execl_return;
char str[2];
char * execl_path_name;
memset(pid_array, 0, sizeof(pid_array));
/* create the MAx file initialized to zero */
for (int i = 1; i < (NUMBER_TRACKS + 1); i++) {
memset(track_name, '\0', sizeof(track_name));
memset(track_number, '\0', sizeof(track_number));
strcpy(track_name, TRACKS_INITIALS);
sprintf(track_number, "%d", i);
strcat(track_name, track_number);
create_track_file(track_name, "", SIZE);
}
execl_path_name = get_file_name(CHILDETCONE, "", SIZE);
printf("path %p\n", execl_path_name);
for(int i = 0; i < NUMBER_TRAINS; i++) {
pid = fork();
if (pid < 0) {
perror("fork");
exit(1);
}
if (pid == 0) { //child
//sprintf(str, "%d", i+1);
//execl_return = execl(execl_path_name, CHILDETCONE, i, NULL);
signal(SIGUSR1, handler);
pause();
exit(0);
}
//parent
pid_array[i] = pid;
}
for (int j = 0; j < NUMBER_TRAINS; j++) {
kill(pid_array[j], SIGUSR1);
sleep(1);
}
for (int i = 0; i < NUMBER_TRAINS; i++) {
wait(NULL);
}
return 0;
}
void handler(int sig) {
printf("printed from child [%d]\n", getpid());
printf("signal [%d]\n", sig);
}
Do I need to insert my execl inside the handler function?
No. pause() will return only after the process in which it is called catches a signal that causes a signal-handling function to run. The execl call can therefore go just after the pause call. I think that would be clearer in your case.
Note, too, that POSIX standardizes a list of "async-signal-safe" functions that are safe for a signal handler to call, and that it is unsafe for a handler to call others. execl is on the list, but printf and other stream I/O functions are not. Signal handlers should not call printf. Your particular signal handler does not need to do anything at all.
Additionally, consider using sigsuspend() in place of pause(), as the former will give you more control over which signals cause your trains to start.
I don't understand the significance of this last loop from the answer
to the previous question:
for (int i = 0; i < NUMBER_TRAINS; i++)
{
wait(NULL);
}
The wait() function instructs the calling process to block until one of its children terminates. The loop makes as many wait() calls as there are children, so that, in the absence of errors, the main program does not proceed until all its children have terminated.
It looks like you may have tried to achieve something similar by calling sleep() in the loop with the kill call, but that strategy is plain wrong. In the first place,
waiting after each kill means that the children's execl calls will be spaced out by at least the sleep time, which is not what I understood you to want. In the second place, you cannot know in advance how long it will take the children to finish, so the one second you allow may not be enough under some circumstances. In the third place, since you seem to expect that the children will run very quickly, one second is probably much more than you need most of the time.
The following program implements two array of threads.There are two thread functions student and teacher(I have not shown them here). My sample program is given below. I want to make a time limit(say 10 sec) after which the main thread will automatically exit no matter if others threads have completed or not.I also want to the current time every moment after starting of the program. How will I do that?
Sample code fragment:
int main(void)
{
pthread_t thread1[25];
pthread_t thread2[6];
int i;
int id1[25]; //for students
int id2[6]; //for teachers
for(i=0;i<25;i++)
{
id1[i]=i;
id2[i]=i;
pthread_create(&thread1[i],NULL,student,(void*)&id1[i] );
if(i<6)
{
pthread_create(&thread2[i],NULL,teacher,(void*)&id2[i]);
}
}
for (i=0;i<25;i++)
{
pthread_join(thread1[i],NULL);
if(i<6)
{
pthread_join(thread2[i],NULL);
}
}
return 0;
}
What additional things will I have to add to the above code to terminate the main thread after a certain time? (say: 10 seconds)
You can use pthread_timedjoin_np() for this passing a timespec struct. You can set the struct to timeout after 10 seconds like this:
struct timespec tp;
tp.tv_sec = 10;
tp.tv_nsec = 0;
Then you change your calls to join pthread_timedjoin_np(myThread, &tp). Regarding how you can get the current time, the simplest method is to use gettimeofday function.
Another perhaps simpler approach is to use a alarm. You can have a function which will exit the application. So you would do something like this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
void alarmhandler(int sig) {
printf("Ten seconds passed, quitting!\n");
exit(0);
}
int main() {
int i, j;
struct timeval end, start;
signal(SIGALRM, alarmhandler);
alarm(4);
gettimeofday(&start, NULL);
sleep(3); // simulate thread work
gettimeofday(&end, NULL);
long elapsed = (end.tv_sec-start.tv_sec)*1000000 + end.tv_usec-start.tv_usec;
printf("%f seconds elapsed!\n", (float)(elapsed)/1000000.0f);
for(;;); // block indefinitely
}
I wrote a C program for the Dining Philosophers Problem using pthread some time ago and am now trying to change it to use fork() instead. This is an exercive for a lecture I already passed. But a friend asked me for help and I can't seem to get it figured out by myself, which is driving me crazy!
If i do a "ps" the processes are there. But there isn't any output to stdout, so I think I'm doing something wrong with the pipes.
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#define N 5
#define LEFT (i+4)%N
#define RIGHT (i+1)%N
#define THINKING 0
#define HUNGRY 1
#define EATING 2
sem_t spoon;
sem_t phil[N];
int state[N];
int phil_num[N]={0,1,2,3,4};
int fd[N][2]; // file descriptors for pipes
pid_t pid, pids[N]; // process ids
int i;
int num;
void philosopher(int i);
void test(int i);
void take_spoon(int i);
void put_spoon(int i);
char buffer[100];
int main(void)
{
for(i=0;i<N;++i)
{
pipe(fd[i]);
pids[i] = fork();
printf("i=%d\n",i);
printf("pids[i]=%d\n",pids[i]);
if(pids[i]==0)
{
// child
dup2(fd[i][1],1);
close(fd[i][0]);
close(fd[i][1]);
philosopher(i);
_exit(0);
}
else if(pids[i]>0)
{
// parent
dup2(fd[i][0],0);
close(fd[i][0]);
close(fd[i][1]);
}
}
// wait for child processes to end
for(i=0;i<N;++i) waitpid(pids[i],NULL,0);
return 0;
}
void philosopher(int i)
{
while(1)
{
sleep(1);
take_spoon(i);
sleep(2);
put_spoon(i);
sleep(1);
}
}
void take_spoon(int i)
{
sem_wait(&spoon);
state[i] = HUNGRY;
printf("philosopher %d is hungry\n",i+1);
test(i);
sem_post(&spoon);
sem_wait(&phil[i]);
}
void put_spoon(int i)
{
sem_wait(&spoon);
state[i] = THINKING;
printf("philosopher %d puts down spoon %d and %d hin\n",i+1,LEFT+1,i+1);
printf("philosopher %d thinks\n",i+1);
test(LEFT);
test(RIGHT);
sem_post(&spoon);
}
void test(int i)
{
if( state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING)
{
state[i] = EATING;
printf("philosopher %d takes spoon %d and %d\n",i+1,LEFT+1,i+1);
printf("philosopher %d eats\n",i+1);
sem_post(&phil[i]);
}
}
Thank you in advance for any help.
Several issues. First is that after fork(), the child process and parent process do not share memory. This is one of the primary differences between a thread and a process. Each process has its own virtual address space. Whatever you want the philosophers to share, you have to explicitly do that by creating shared memory. It seems you intended your global variables to be shared among all the processes. (Note that there are some things shared, such as open file descriptors, and the child does get a copy of the variables from the parent, initialized to the values that were assigned to them at the time of the fork() call.)
Second, you have some confusingly unnecessary variables. In particular, the pipes do not serve any real purpose. The stdout for each of the processes will go to the console screen already, without the need for trying to pipe them back to the parent. This is because the child process already inherits the open file descriptors of the parent, so the child will already be using the same stdout as the parent. In addition, the phil_num, and num variables were unused, and the i. pid and pids variables seemed to be needlessly made global.
Third, you failed to initialize your semaphores. The default initialization as a global variable probably leaves the semaphore "useable" but with a 0 initial value, meaning sem_wait() on it will just block. In your case, you need those semaphores in shared memory, so a call to sem_init() is mandatory anyway (to indicate it is going to be shared between multiple processes), and the call gives you a chance to properly initialize the semaphore with a value of 1 so that the initial sem_wait() call has a chance to return.
After adjusting the globals down to what really needs to be shared, they can be bundled together into a structure. Then, a global pointer can be created for the shared data.
struct shared_data {
sem_t spoon;
sem_t phil[N];
int state[N];
};
struct shared_data *shared;
void initialize_shared(); /* at program start */
void finalize_shared(); /* at program end */
One way to create shared memory is to use mmap(). After the memory is created, the data should be initialized properly. This includes a call to sem_init() on the semaphores. sem_destroy() is used to clean up a semaphore, and the mapped memory can be released with munmap(). These are done for you when the process exits, but provided for completeness. (You should always check the return values of all the operating system calls you make, but I have elided them for the sake of brevity.)
void initialize_shared()
{
int i;
int prot=(PROT_READ|PROT_WRITE);
int flags=(MAP_SHARED|MAP_ANONYMOUS);
shared=mmap(0,sizeof(*shared),prot,flags,-1,0);
memset(shared,'\0',sizeof(*shared));
sem_init(&shared->spoon,1,1);
for(i=0;i<N;++i) sem_init(&shared->phil[i],1,1);
}
void finalize_shared()
{
int i;
for(i=0;i<N;++i) sem_destroy(&shared->phil[i]);
munmap(shared, sizeof(*shared));
}
Your main() implementation does not really change, except you need to add local variables for the ones that were needlessly global, as well as call initialize_shared() and optionally finalize_shared(). Also, remove all the code related to pipe().
int main(void)
{
int i;
pid_t pid, pids[N]; // process ids
initialize_shared();
for(i=0;i<N;++i)
{
pid = fork();
if(pid==0)
{
// child
philosopher(i);
_exit(0);
}
else if(pid>0)
{
// parent
pids[i] = pid;
printf("pids[%d]=%d\n",i,pids[i]);
}
else
{
perror("fork");
_exit(0);
}
}
// wait for child processes to end
for(i=0;i<N;++i) waitpid(pids[i],NULL,0);
finalize_shared();
return 0;
}
Note that your program never really exits on its own, since philosopher() is implemented as an infinite loop.