emanyalpsid
emanyalpsid

Reputation: 329

Signals between 2 programs

If one program sendS a signal to the second program, can the second program figure out what the pid of the first program is just by the signal sent by it?

First Program: (Code is incomplete, signals is the main focus)

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

void my_handler(int);


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


    FILE *fp;
    fp=fopen(argv[1], "w");

    kill(atol(argv[2]),SIGUSR1);
}

Second Program:

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

void my_handler(int signum){
            if (signum == SIGUSR1)
            {
                    printf("Received SIGUSR1!\n");
            }
}

int main(int argc, char *argv[]){
    int pid;
    pid=getpid();
    printf("PID: %d\n", pid);

    signal(SIGUSR1, my_handler);

    pause();
}

Is there a way? Or should i put the pid of the first program in SIGUSR1 somehow and the second program can figure out the pid?

Upvotes: 4

Views: 2540

Answers (3)

Jonathan Leffler
Jonathan Leffler

Reputation: 754880

Assuming you are on a sufficiently POSIX-compatible system, then you can get the information if you set the signal handling with sigaction(), if you specify a signal handler that takes a siginfo_t pointer, and you specify SA_SIGINFO as one of the flags:

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static siginfo_t sig_info;
static volatile sig_atomic_t sig_num;
static void *sig_ctxt;

static void catcher(int signum, siginfo_t *info, void *vp)
{
    sig_num = signum;
    sig_info = *info;
    sig_ctxt = vp;
}

static void set_handler(int signum)
{
    struct sigaction sa;
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = catcher;
    sigemptyset(&sa.sa_mask);

    if (sigaction(signum, &sa, 0) != 0)
    {
        int errnum = errno;
        fprintf(stderr, "Failed to set signal handler (%d: %s)\n", errnum, strerror(errnum));
        exit(1);
    }
}

static void prt_interrupt(FILE *fp)
{
    if (sig_num != 0)
    {
        fprintf(fp, "Signal %d from PID %d\n", sig_info.si_signo, (int)sig_info.si_pid);
        sig_num = 0;
    }
}

int main(void)
{
    set_handler(SIGINT);
    pause();
    prt_interrupt(stdout);
    return(0);
}

Compile as 'catch' and run:

$ ./catch &
[1] 31165
$ kill -2 31165
Signal 2 from PID 26983
$ echo $$
26983
[1]+  Done                    ./catch
$

Upvotes: 1

Barath Ravikumar
Barath Ravikumar

Reputation: 5836

You can create a shared memory between the two process. From the 1st process , obtain the pid using getpid() , and save it to the shared memory area.

ShmID   = shmget(PidKey, sizeof(pid_t), IPC_CREAT | 0666);
ShmPTR  = (pid_t *) shmat(ShmID, NULL, 0);

In the second process , inside your handler just attach your c program to the shared memory area

void my_handler(int signum)
{
 if (signum == SIGUSR1)
 {

  ShmID   = shmget(PidKey, sizeof(pid_t), 0666);
  ShmPTR  = (pid_t *) shmat(ShmID, NULL, 0);
  pid     = *ShmPTR
 }
}

At the end of the program , do clean up the shared memory

shmdt(ShmPTR);
shmctl(ShmID, IPC_RMID, NULL);

Note - The code above is far from complete , no semaphores are used and no other measures are taken against race conditions in a multiprocessor environment.

Upvotes: -1

nneonneo
nneonneo

Reputation: 179687

Assuming you mean POSIX signals, then yes. You can access the sender's PID through the si_pid member of siginfo_t, though you will need to use sigaction and the SA_SIGINFO flag to define your handler.

Non-POSIX systems (e.g. Windows) may not even have the concept of a signal (at least not in the POSIX sense), so none of this will apply.

Upvotes: 1

Related Questions