1

Trying to implement signal handlers but receiving the warning:

assignment from incompatible pointer type [enabled by default]
   act.sa_sigaction = sigChldHandler;

... Also my professor pointed out.

char * argv[3];
argv[0]= GUESSER_PROGNAME;
argv[2]= NULL;

this allocates memory for 3 char pointer vars, but they do NOT point anywhere in particular." But I am not sure what he means by that.

\file 1

#include "assign2Headers.h"
pid_t answererPid;
pid_t guesserPid;

int shouldRun = 1;

void  sigAlrmHandler(int sig)
{
    kill(answererPid,TIME_OVER_SIGNAL);
    kill(guesserPid,TIME_OVER_SIGNAL);
    shouldRun=0;
}

void  sigChldHandler(int sig)
{
wait(NULL);
shouldRun=0;
}

int main(void){


  struct sigaction act;
  memset(&act, '\0', sizeof(struct sigaction));

  act.sa_handler = sigAlrmHandler;
  sigaction(SIGALRM, &act, NULL);

  act.sa_sigaction = sighldHandler;
  sigaction(SIGCHLD, &act, NULL);


char line[LINE_LEN];
char * argv[3];
argv[0]= GUESSER_PROGNAME;
argv[2]= NULL;
answererPid = fork();

if(answererPid == 0){

        execl(ANSWERER_PROGNAME,ANSWERER_PROGNAME,(char*)NULL);

    }

else{
        sleep(1);
        snprintf(line,LINE_LEN,"%d",answererPid);
        guesserPid=fork();
        if(guesserPid==0)
        {
            execl(GUESSER_PROGNAME,GUESSER_PROGNAME,argv[0],line,(char*)NULL);
        }
        else
        { alarm(NUM_SECONDS);
            while(shouldRun)
                sleep(1);
            sleep(1);
            sleep(1);
            printf("launcher finished\n");
            return (EXIT_SUCCESS);

        }

    }

}

\file 2

#include "assign2Headers.h"

int shouldRun = 1;

void timeoverhandler(int sig)
{   sleep(1);
    printf("\nOh no!  The time is up!\n");
    printf("guesser finished\n");
    shouldRun=0;
    exit(EXIT_SUCCESS);
}

void winsignalhandler(int sig)
{
    printf("\nCongratulations!  You found it!\n");
    shouldRun=0;
        signal(WIN_SIGNAL,winsignalhandler);
}

void correctsignalhandler(int sig)
{
    printf("Yay!  That was right!\n");
    signal(CORRECT_SIGNAL,correctsignalhandler);
}

void incorrectsignalhandler(int sig)
{
    printf("Oops!  That was wrong.  Please restart from the beginning.\n"
"\nRe-starting from the beginning:\n");
    signal(INCORRECT_SIGNAL,incorrectsignalhandler);
}

int main(int argc,char* argv[])
{

    pid_t answererPid=atoi(argv[1]);
    signal(TIME_OVER_SIGNAL,timeoverhandler);
    signal(WIN_SIGNAL,winsignalhandler);
    signal(CORRECT_SIGNAL,correctsignalhandler);
    signal(INCORRECT_SIGNAL,incorrectsignalhandler);

    while(shouldRun)
    {   int guess;
        printf("What would you like your next guess to be: 0 or 1? ");
        scanf("%d",&guess);
        if(guess==0)
            kill(answererPid,ZERO_SIGNAL);
        if(guess==1)
            kill(answererPid,ONE_SIGNAL);
        sleep(2);

    }


    printf("guesser finished\n");
    return (EXIT_SUCCESS);


}

\file 3

//---       Common standard header files                ---//

#include    <stdlib.h>
#include    <stdio.h>
#include    <string.h>
#include    <signal.h>
#include    <sys/types.h>
#include    <sys/wait.h>
#include    <unistd.h>

////---     Common constants:                   ---//

#define     ZERO_SIGNAL     SIGUSR1    
#define     ONE_SIGNAL      SIGUSR2
#define     CORRECT_SIGNAL      SIGUSR1
#define     INCORRECT_SIGNAL    SIGUSR2
#define     WIN_SIGNAL      SIGINT
#define     TIME_OVER_SIGNAL    SIGTERM

#define     GUESSER_PROGNAME    "guesser"
#define     ANSWERER_PROGNAME   "answerer"

#define     LINE_LEN        256
#define     NUM_SECONDS     30

\file 4

//---       Inclusion of header files               ---//

#include    "assign2Headers.h"

//---       Definition of constants:                ---//

#define     PATTERN_LEN 4

//---       Definition of global vars:              ---//

int     answer;
int     numCorrect  = 0;
int     shouldRun   = 1;


//---       Definition of global fncs:              ---//

void        timeUpHandler   (int        sig
                )
{
  shouldRun = 0;
}


void        guessHandler    (int        sig,
                 siginfo_t* infoPtr,
                 void*      dataPtr
                )
{
  int   toSendBack;
  int   userBit     = (sig == ONE_SIGNAL);
  int   correctBit  = ((answer >> numCorrect) & 0x1);
  int   isCorrect   = (correctBit == userBit);

  printf("position %d: userBit %d, correctBit %d\n",
     numCorrect,userBit,correctBit
    );

  if  (isCorrect)
  {
    numCorrect++;

    if  (numCorrect >= PATTERN_LEN)
      toSendBack = WIN_SIGNAL;
    else
      toSendBack = CORRECT_SIGNAL;
  }
  else
  {
    numCorrect  = 0;
    toSendBack  = INCORRECT_SIGNAL;
  }

  kill(infoPtr->si_pid,toSendBack);
}


int     main        (int    argc,
                 char*  argv[]
                )
{
  //  I.  Application validity check:

  //  II.  Run program:
  //  II.A.  Initialize random number generator and choice:
  srand(getpid());

  answer    = rand() % (1 << PATTERN_LEN);

printf("(The answer is %d)\n",answer);

  //  II.B.  Install signal handlers:
  struct sigaction  act;

  memset(&act,'\0',sizeof(act));
  act.sa_handler    = timeUpHandler;
  sigaction(TIME_OVER_SIGNAL,&act,NULL);

  act.sa_flags      = SA_SIGINFO;
  act.sa_sigaction  = guessHandler;
  sigaction(ZERO_SIGNAL,&act,NULL);
  sigaction(ONE_SIGNAL,&act,NULL);

  //  II.C.  Hand out while game still active:
  while  ( (numCorrect < PATTERN_LEN)  &&  shouldRun )
    sleep(1);

  //  III.  Finished, return answer:
  printf("answerer finished\n");
  return(EXIT_SUCCESS);
}

how do I remove this warning and what does he mean by that? Someone help me please.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
J. Doe
  • 11
  • 1
  • 4

2 Answers2

4

I guess you are working on Linux. From sigaction manpage :

   struct sigaction {
       void     (*sa_handler)(int);
       void     (*sa_sigaction)(int, siginfo_t *, void *);
       sigset_t   sa_mask;
       int        sa_flags;
       void     (*sa_restorer)(void);
   };

The prototype void sigChldHandler(int sig) does not match with sa_sigaction. Hence the warning.

You can use

  1. sa_handler to set the signal handler function or to specify SIG_IGN/SIG_DFL actions.
  2. sa_sigaction to set the signal handler function - if user needs to access more details like user context and siginfo structure (sender process details, signal type etc). Need to set SA_SIGINFO in the sa_flags for this usage.

For your case, setting sa_handler might be sufficient.

In main():

struct sigaction act;
act.sa_handler = sigChldHandler;
act.sa_flags = SA_RESTART;
sigaction(SIGCHLD, &act, NULL);

Also,

  1. Use separate sigaction structures per signal that you want to set unless you want same handler for them.
  2. Do not mix sigaction() & signal() usages. Stick to one. Maybe, sigaction as it's new & provides more features than signal().
alk
  • 69,737
  • 10
  • 105
  • 255
ReddyVeeru
  • 136
  • 6
  • 1
    Please show how to change(replace this to that ) it in the answer so as to help future visiting members – minigeek Feb 09 '17 at 05:30
  • so i would replace: {struct sigaction act; memset(&act, '\0', sizeof(struct sigaction)); act.sa_handler = sigAlrmHandler; sigaction(SIGALRM, &act, NULL);} with {struct sigaction act; act.sa_handler = sigAlrmHandler; act.sa_flags = SA_RESTART; sigaction(SIGALRM, &act, NULL);}}..? – J. Doe Feb 09 '17 at 12:14
  • For each signal that you want to handle, add the four lines like I mentioned. You need to use a separate sigaction structure variable (like act1, act2...) for each signal. – ReddyVeeru Feb 09 '17 at 12:17
1

This segment:

char * argv[3]; 
argv[0]= GUESSER_PROGNAME; 
argv[2]= NULL;

Is invalid for argv[0]. Since argv is an array of pointers, you need to make sure those pointers are pointing somewhere before you use them.

This can be achieved with strdup():

argv[0]= strdup(GUESSER_PROGNAME);

Or with malloc()/strcpy():

argv[0]= malloc(strlen(GUESSER_PROGNAME)+1);
strcpy(argv[0], GUESSER_PROGNAME);

Note: malloc() should also be checked, it can return NULL on failure. Any memory allocated on the heap should also be free()'d at the end.

In terms of clarity, you could replace:

#define GUESSER_PROGNAME "guesser"

with:

const char *guesser_progname = "guesser";
RoadRunner
  • 25,803
  • 6
  • 42
  • 75
  • 1
    "*Is invalid for `argv[0]`*": Assuming `#define GUESSER_PROGNAME "...."` this `char * argv[3]; argv[0]= GUESSER_PROGNAME;` is perfectly valid. Did you mean to refer to the validity of `argv[1]`? – alk Feb 12 '17 at 09:38