Search code examples
clinuxtimeforkexec

Random sleep execlp bad address on program to check the execution time of programs


I’m trying to make a simple program using fork() to execute a command or program and see if it finishes under the time limit that I introduce by parameter like this:

Input:

    ./timechecker 3 ls ps ls

So what I know is that I finished the execlp correctly with the NULL at the end but I don't know why I'm getting random results from the sleep execlp sometimes it says bad address and it says on my output that the programs associated with that run have been forced to finish but it happens independently of the time I use. Example output:

execlp sleep: Bad address                   //The ls execlp
  PID TTY          TIME CMD                //The ls execlp without sleep error
execlp sleep: Bad address                  //The ps execlp
  225 pts/3    00:00:00 a.out              //The ps without sleep error
  231 pts/3    00:00:00 ps
  232 pts/3    00:00:00 a.out <defunct>
  PID TTY          TIME CMD
  225 pts/3    00:00:00 a.out
  233 pts/3    00:00:00 ps
  234 pts/3    00:00:00 a.out
Total time: 0 
1 programs have been forced to finish taking more than 1000 seg and 2 programs have been finished under the time limit

The code:

        #include <sys/types.h>
        #include <unistd.h>
        #include <stdio.h>
        #include <time.h>
        #include <sys/wait.h>
        #include <stdlib.h>
        #include <string.h>
        #include <signal.h>
        #define error(a){perror(a);exit(1);}
        
        int main(int argc, char *argv[]) //argv1 timeLimit argv2..argv11 commands
        {
        
            if (argc > 12 || argc < 3)
            {
                error("Incorrect number of arguments");
            }
            
            int timeLimit = atoi(argv[1]);
        
            if(timeLimit < 0)
            {
                error("The time limit must be 0 or greater")
            }
            
            int programs = argc - 2;
            int forced = 0;
            int finished = 0;
            char program[100] = "";
        
            int i = 0, pid, pid_clock, pid_dev = 0, estatus;
        
            time_t t1, t2;
        
            t1 = time(NULL);
        
            while(i<programs) //i<nb_tests
            {
                pid = 0;
                pid_clock = 0;
                estatus = -1;
                t2 = time(NULL);
                pid = fork();
                switch(pid)
                {
                    case -1:
                        error("fork")
                    case 0:
                        strcpy(program, argv[i]);
                        execlp(program, program, NULL);
                        error("execlp programm");
                    default:
                        pid_clock = fork();
                        switch(pid_clock)
                        {
                            case -1:
                                error("fork")
                            case 0:
                                execlp("sleep", "sleep", timeLimit, NULL); //The problem
                                error("execlp sleep");
                            default:
                                pid_dev = wait(NULL);
                                if(pid_dev == pid_clock)
                                {
                                    kill(pid, SIGKILL);
                                    wait(NULL);
                                    estatus = 0;
                                    break;
                                }
                                else if(pid_dev == pid)
                                {
                                    kill(pid_clock, SIGKILL);
                                    wait(NULL);
                                    estatus = 1;
                                    break;
                                }
                                else 
                                {
                                    printf("%d\n", pid_dev);
                                    estatus = -1;
                                    break;
                                }
                        }
                }
                t2 = time(NULL) - t2;
                
                if(estatus == 0)
                {
                    forced++;
                }
                else if(estatus == 1)
                {
                    finished++;
                }
                i++;
            }
        
            t1 = time(NULL) - t1;
        
            printf("Total time: %li \n", t1);
            printf("%d programs have been forced to finish taking more than %d seg and %d programs have been finished under the time limit\n",forced, timeLimit, finished);
        
            return 0;
        }

Solution

  • The arguments to the command used for the exec functions is a list of strings. They are, effectively, what becomes the string array argv in the executed program.

    You pass an integer value as the argument for the sleep command, not a string. That leads to undefined behavior and very likely crashes.