简体   繁体   中英

Queries in signalling between processes Linux

Hi I'm just working on signalling between two processes. I have a main process (eg. MAIN ) which keeps on running. This MAIN is forked from a Wrapper process (eg. WRAP ).

Here is my code which will actually launch the WRAP process, which in turn will create a child process as MAIN .

When certain initialization is completed in MAIN I would like to post a signal SIGUSR1 , which will be captured by WRAP and does some other stuffs.

The problem with my code is when the signal is raised from MAIN it is never trapped by WRAP process. Pls. share your suggestions on this code or if there are any other ways to achieve this. Thank you.

In MAIN process:

After Init is completed I have added this code,

main()
{
    // Do some work here
    int pid = GetProcessID(); // Returns the process ID of WRAP process
    kill(pid,SIGUSR1);        // Tries to send signal to WRAP process

    // Other code
}

int GetProcessID()
{
    int pid = 0;
    char results[128];
    FILE *fp = popen("pgrep WRAP", "r");
    if(fp == NULL)
    {
        printf("Error: Failed to get Process ID");
    }
    else
    {
        while(fgets(results, 128, fp) != NULL)
        {
            pid = atoi(results);
        }
        pclose(fp);
    }
    return pid;
}

In WRAP process:

main()
{ 
    int pid;

    signal(SIGUSR1,InitComplete);

    if ((pid = fork()) < 0) 
    {
        perror("fork");
        exit(1);
    }

    if (pid == 0)
    { 
        /* child */
        system("mainProc.out");
    }
    else 
     {  
        /* parent */
        if(KeepListening() == 1)
            printf("Init completed successfully\n");
    }

    return 0;
}

int KeepListening()
{
    const int MAX_WAIT_TIME = 180;
    int procStarted = 0;
    int res = 0;
    sigset_t origset;
    sigset_t ss;

    sigemptyset(&ss);
    sigaddset(&ss, SIGWINCH);
    sigaddset(&ss, SIGUSR1);
    res = sigprocmask(SIG_BLOCK, &ss, &origset);

    if(res)
    {
        printf("\nError: sigprocmask returned an error\n");
    }

    struct timespec theTimeout;
    theTimeout.tv_nsec = 0;
    theTimeout.tv_sec = MAX_WAIT_TIME;

    int sig = 0;
    siginfo_t theInfo;
    memset(&theInfo, '\0', sizeof(theInfo));

    int timedwaitcount = 0;

    do
    {
        sig = sigtimedwait(&ss, &theInfo, &theTimeout);
        if(sig < 0)
        {
            if(EAGAIN == errno)
            {
                timedwaitcount++;
            }
            else
            {
                PrintMessage("Error:Error occured with sigtimedwait\n");
            }
        }
        else
        {
            timedwaitcount = 0;
        }

        if(SIGUSR1 == sig)
        {
            return 1;
        }
    }while(SIGWINCH == sig || 0 == sig);

    return procStarted;
}

void InitComplete()

   printf("InitComplete in MAIN. Signal Received.\n");
}

I prepared a short sample which demonstrates how it should work.

Source file test-exec.c for what you call WRAPPER:

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

static int sigUsr1Rcvd = 0;

enum { SleepTimeUS = 50000 /* us */ };

void onSigUsr1(int sig)
{
  if (sig == SIGUSR1) sigUsr1Rcvd = 1;
}

int main(int argc, char **argv)
{
  int pid; char buffer[20]; int status = 0;
  /* report alive */
  printf("%s started...\n", argv[0]);
  /* install signal handler before fork() */
  signal(SIGUSR1, &onSigUsr1);
  /* fork child */
  if (pid = fork()) { /* main process */
    if (pid < 0) {
      perror("ERROR in fork()");
      return -1;
    }
  } else { /* child process */
    if (execl("./test-exec-child", "test-exec-child", NULL)) {
      perror("ERROR in execl()");
      return -1;
    }
    return 0;
  }
  /* main process */
  /* waiting for SIGUSR1 */
  while (!sigUsr1Rcvd) usleep(SleepTimeUS);
  printf("%s: Child inited.\n", argv[0]);
  /* wait for termination of child */
  wait(&status);
  /* done */
  printf("%s exiting...\n", argv[0]);
  return 0;
}

Source code file test-exec-child.c for what you call MAIN:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

enum { SleepTimeS = 3 /* s */ };

int main(int argc, char **argv)
{
  char buffer[20];
  /* report alive */
  printf("%s started...\n", argv[0]);
  /* consume some time */
  printf("%s: initializing...\n", argv[0]);
  sleep(SleepTimeS);
  printf("%s: done.\n", argv[0]);
  /* send signal to parent */
  kill(getppid(), SIGUSR1);
  /* spend time until user feed-back */
  printf("Press [ENTER] to continue...");
  fgets(buffer, sizeof buffer, stdin);
  /* done */
  printf("%s exiting...\n", argv[0]);
  return 0;
}

I compiled and tested this with gcc on cygwin:

$ gcc -o test-exec test-exec.c

$ gcc -o test-exec-child test-exec-child.c

$ ./test-exec
./test-exec started...
test-exec-child started...
test-exec-child: initializing...

...

test-exec-child: done.
./test-exec: Child inited.
Press [ENTER] to continue...

[ENTER]

test-exec-child exiting...
./test-exec exiting...

$

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM