1

I'm trying to do a ping pong exercise, I ask for guidance / direction but not a solution so I can learn.

Workspace: ubuntu 19

Language: C.

The task is like this:

  • Do not use () fork
  • The ping process is waiting for a signal
  • The Pong process gets the Ping PID from the command line as an argument
  • Pong should send SIGUSER1 signal to ping
  • Ping returns a signal SIGUSER2 to pong and so on ...
  • run 2 processes from gdb.

My questions are like this:

  1. How do I pass the pid as a command line argument?
  2. How do I read the PID in the second process?
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
moses
  • 15
  • 4
  • Do you know how to use command-line arguments? – user253751 Jun 22 '20 at 13:39
  • Yes, I know how to use it but I do not understand how to pass between 2 running processes – moses Jun 22 '20 at 13:47
  • 1. run `ping` 2. find PID of `ping`. 3. if the PID is 1234 then run `pong 1234` – user253751 Jun 22 '20 at 13:50
  • You can't give `pong` the PID of `ping` through the signal. You need another way. – the busybee Jun 22 '20 at 14:14
  • You pass the PID as a string — all command-line arguments are strings. If you're not allowed to use `fork()` in `ping.c` or `pong.c`, you either write a controller program that runs both `ping` and `pong` (using `fork()` and `exec()`) or you run both programs in the debugger (as the last bullet point suggests) with two separate sessions (two separate windows), but pass the PID of `ping` in the debugger session that runs `pong`. – Jonathan Leffler Jun 22 '20 at 16:54

1 Answers1

1

so, the question makes perfect sense. This is an exercise in using signals and signal handlers.

Pong.c will have something like (but you should add error handling yourself if, for example, there is no pid):

#include <sys/types.h>
#include <unistd.h>
#include <signal.h>

void sigHandler( int signo, siginfo_t *siginfop, void *context)
{
   /* send another signal back to ping, you dont need the pid you read from cmd line */ 
   union sigval sv;
   if( siginfop != NULL )
       sigqueue( siginfop->si_pid, SIGUSR1, sv)
 }
      
void main( int argc, const char *argv[] )
{
   int ping_pid = atoi(argv[1]);
   
   /* this is for receiving signals */
   struct sigaction sa;
   sa.sigaction = sigHandler;
   sigemptyset(&sa.sa_mask);
   sa.sa_flags = SA_NODEFER | SA_SIGINFO;
   
   /* you send SIGUSR1 from pong; you'll receive SIGUSR2 from ping */
   if( sigaction(SIGUSR2, &sa, NULL) == -1) perror("sigaction");
   

  /* this is for sending the first signal */
   union sigval sv;
   
   if( sigqueue( ping_pid, SIGUSR1, sv) == -1 ) perror("sigqueue")
   /*
    do something
    while u wait
   */
  }

And for the other program, in ping.c you do the same, except you dont read a pid off the command line, you just wait for the other processes signal; and the signal id's are the other way round (or however you need it).

secret squirrel
  • 802
  • 9
  • 13
  • Transmitting the sender's _pid_ in `sival_int` is not necessary. `si_pid` will be filled in for a SI_USER/SI_QUEUE (`si_code`) signal caught in a SA_SIGINFO handler. – pilcrow Jun 22 '20 at 18:16
  • @pilcrow aha yeah you're right, sival_int isn't for that, the pid gets filled automatically, well spotted. I'll edit the answer, thanks. – secret squirrel Jun 22 '20 at 19:11
  • no sweat, glad it was useful, if you could accept the answer the question can be closed, thanks ! – secret squirrel Jun 23 '20 at 06:16