2

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

Community
  • 1
  • 1
Melclic
  • 31
  • 4
  • AFAIK, there is no way to do this asynchronously in pure C. You either have to poll (`time()`) in your function, or you need to accept some dependency on your implementation (in POSIX, it's pretty easy with `timer_create()/sigaction()/timer_settime()`). – EOF Jul 30 '15 at 10:42

2 Answers2

1

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

valegians
  • 850
  • 1
  • 7
  • 17
  • Thanks that makes a lot of sense! I was reading that others have successfully done this using threading. I will explore that route. – Melclic Jul 30 '15 at 11:18
  • Here is a link to some tutorial for threads in Linux if you want http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html – valegians Jul 30 '15 at 11:26
0

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.

Melclic
  • 31
  • 4