0

UPDATE:When I set act.sa_flags = SA_RESTART the program stops seg faulting however it causes the program to be "stuck" in that function, as in it doesn't move forward with the logic in my program. The colon indicates the beginning of a new command line input. The ideal output is below:

 : ls
 smallsh.c small
 : sleep 5 & //background process
 : ls > junk
 background pid # is complete terminated by signal $ //when background sleep finishes
 :

However I'm getting the following now:

 : ls
 smallsh.c small
 : sleep 5 & //background process
 : ls > junk
 background pid # is complete terminated by signal $ 
 //cursor is pointing here but no colon appears, i can still write commands
 //and they will work but function believers they are all background processes

PREVIOUS: I'm trying to code a simple shell with background and foreground processes in C. In order to create a background process the user must input a "&" at the end of their command so for example "sleep 3 &" would be a background process. In my program when I enter "sleep 3 &" the process successfully runs but upon completion when the sig handler function is called a statement is printed (which states the background process has ended) and then the program seg faults. Here's an example of what the output looks like:

: sleep 3 & background pid is 22688 : background pid 0 is done: terminated by signal 0 Segmentation fault: 11

My signal handler is called when I try to run a background process and I'm not sure why. When I set the sigaction to use SIGINT the program doesn't seg fault. Any thoughts? I saw a similar post here (SIGCHLD causing segmentation fault, not going into handler) but it didn't help me.

pid_t spawnPID = -5
int exitMethod; 
int exitStatus = 0;
char bgPID[10];

//Set up signal handler
struct sigaction act;
act.sa_handler = sig_handler;
act.sa_flags = 0;
sigfillset(&(act.sa_mask));

fflush(stdout);


if (bg == 1)
{
 sigaction(SIGCHLD, &act, NULL);
}


switch(spawnPID)
{
    case -1:
    {
        //There was an error forking
        printf("Error forking\n");
        fflush(stdout);
        exitStatus = 1; 
    }
    case 0:   //Child process
    {

        //Check for input/output redirection
        if (numArgs > 1)
        {

            if (!(strncmp(arguments[1], ">", 1)))
            {

                exitStatus = outputRedirect(arguments,numArgs);
            }
            else if (!(strncmp(arguments[1], "<", 1)) || (! 
            (strncmp(arguments[0], "cat", 1))))
            {
                exitStatus = inputRedirect(arguments,numArgs);
            }
            else
            {

            arguments[numArgs] = NULL; //set last value in the array to NULL 


            if (execvp(arguments[0],arguments) == -1)
            {
                printf("Command or file not recognized\n"); //won't run unless there is an error
                fflush(stdout);
                exitStatus = 1;
            }
        }
    }
        else //run other command
        {

            if (execvp(arguments[0],arguments) == -1)
            {
                printf("%s: No such command, file or directory\n", arguments[0]); //won't run unless there is an error
                fflush(stdout);
                exitStatus = 1;
            }

        }
        break;

    }
//Following code is in the parent case of the switch statement

default:



if (bg == 0)  //waitpid is only called in a parent in a foreground process
{
  pid_t exitpid = waitpid(spawnPID,&exitMethod,0); //Wait for one of the     
  //children to be completed
{


 if (WIFEXITED(exitMethod))
 {
   int exitStatus = WEXITSTATUS(exitMethod);
 }


 //Sig Handler function

void sig_handler (int signo)
{
  int status;
  pid_t childPid;
  char bgMessage[50];
  char bgPID[10];
  char exitStatus[10];

  childPid = waitpid(-1, &status, 0);


  sprintf(bgPID,"%d",childPid);
  sprintf(exitStatus,"%d",WEXITSTATUS(status));
  strcat(bgMessage,"background pid ");
  strcat(bgMessage,bgPID);
  strcat(bgMessage," is done: terminated by signal " );
  strcat(bgMessage,exitStatus);
  strcat(bgMessage,"\n");

  // Write out the message
  write(1, bgMessage, sizeof(bgMessage));
}
Community
  • 1
  • 1
user2466886
  • 205
  • 1
  • 3
  • 14
  • Please explain your code more. I don't understand how it goes with the question. – Whitecat Nov 19 '15 at 02:02
  • "SIGCHLD keeps seg faulting". `SIGCHLD` is a signal name/number so it can't be seg faulting. Where exactly does the seg fault occur? But for starters, do not call `printf` in a signal handler. `printf` is not async safe. – kaylum Nov 19 '15 at 02:08
  • Provided more context and yeah I updated my code so it didn't use printf but that didn't fix the issue. – user2466886 Nov 19 '15 at 02:14
  • Use a debugger to find out exactly which line of code is seg faulting. – kaylum Nov 19 '15 at 02:19
  • 1
    Your program has undefined behaviour. `bgMessage` is used unintialised. `strcat` parameters must be valid strings (including an empty string) whereas your `bgMessage` has garbage in it. – kaylum Nov 19 '15 at 02:23
  • You can use one safe `snprintf` instead of a few unsafe `strcat`. – someuser Nov 19 '15 at 03:39

0 Answers0