Thread: Handler - get PID of child process

  1. #1
    Registered User
    Join Date
    Nov 2020
    Posts
    12

    Handler - get PID of child process

    Code:
    #include <stdio.h>#include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
    #include <string.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <sys/wait.h>
    
    
    int const pipeCount = 1;
    int pipes[pipeCount][2];
    
    
    
    
    #undef si_pid
    
    
    void handler_readPipeSIGIO(int sig, siginfo_t *info, void *secret) 
    {
    
    
        printf( "info->_sifields._sigchld.si_pid: %x\n",  info->_sifields._sigchld.si_pid);
    
    
        char buf[ 333 ];
        int ret = read(pipes[0][0], buf, sizeof( buf ));
        if ( ret < 0 ) 
        {
            printf( "Read fail! %d\n", sig);
            fflush(stdout);
        }
        else
        {
            buf[ ret ] = 0;
            printf( "Read data form Process: %s", buf );
            fflush(stdout);
        }
    
    
    }
    
    
    int main () 
    {
        // Create Pipes
        for(int i = 0; i<pipeCount; i++)
        {
            pipe(pipes[i]);
        }
    
    
        // Create Children
        for(int j = 0; j<pipeCount; j++)
        {
            if(fork()==0)
            {
            //CloseAllPipiesButTheOne
                for(int i=0; i<pipeCount; i++)
                {
                    close(pipes[i][0]);
                    //printf("Process %d Pipe %d End 0 is CLOSE\n", j, i);
                    if(j==i)
                    {
                        ///printf("Process %d Pipe %d End 1 is OPEN\n", j, i);
                        //printf("MyChildD %d \n", getpid());
                    }
                    else
                    {
                        //printf("Process %d Pipe %d End 1 is CLOSE\n", j, i);
                        close(pipes[i][1]);
                    }
                }
                //fflush(stdout);
                //Write data to 0 End of pipes ... 
                while ( 1 )
                {   
                    //printf("Writing to Pipe from Child - %d \n", getpid());
                    fflush(stdout);
                    char buf[ 333 ];
                    //sprintf( buf, "Pid: (%d) Random Number: %d\n", getpid(), rand() % 10000 );
                    sprintf( buf, "Pid: (%d)\n", getpid());
                    write( pipes[j][1], buf, strlen( buf ) );
                    sleep( 2 + rand() % 5 );
                }
                return 0;
            }
        }
    
    
        //close Pipes
        for(int i=0; i<pipeCount; i++)
        {
            close(pipes[i][1]);
        }
    
    
        //SigAction Define
    
    
        struct sigaction sa;
        sa.sa_sigaction = handler_readPipeSIGIO; 
        sa.sa_flags = SA_RESTART | SA_SIGINFO; 
        sigemptyset( &sa.sa_mask ); 
    
    
        sigaction(SIGIO, &sa, NULL);
    
    
        //config read reaction for SIGIO
    
    
        for(int i=0; i<pipeCount; i++)
        {
            fcntl( pipes[i][0], F_SETFL, fcntl( pipes[i][0], F_GETFL ) | O_ASYNC );
            fcntl( pipes[i][0], F_SETSIG, SIGIO );
            fcntl( pipes[i][0], F_SETOWN, getpid() );
        }
    
    
    
    
        printf("Some out ... \n");
        fflush(stdout);
        while(1) sleep (1);
        //wait(NULL);
        return(0);
    }
    and my output is
    Code:
    info->_sifields._sigchld.si_pid: 41Read data form Process: Pid: (6327)
    info->_sifields._sigchld.si_pid: 41
    Read data form Process: Pid: (6327)
    info->_sifields._sigchld.si_pid: 41
    Read data form Process: Pid: (6327)
    where is my mistake?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,736
    > where is my mistake?
    How do we know what you were expecting?

    You shouldn't be calling printf in signal handlers.
    signal-safety(7) - Linux manual page
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Nov 2020
    Posts
    12
    Quote Originally Posted by Salem View Post
    > where is my mistake?
    How do we know what you were expecting?

    You shouldn't be calling printf in signal handlers.
    signal-safety(7) - Linux manual page
    ok I expressed myself wrong
    i am using prinf in handler only for debug ...

    So my questing is: How a get i PID of process witch calling a Handler?

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,736
    Your code doesn't compile.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Feb 2019
    Posts
    886
    Quote Originally Posted by Empair View Post
    So my questing is: How a get i PID of process witch calling a Handler?
    Didn't you mean how to get the PID of the process dispatching the signal? Because the PID of the process "calling" the handler will be the same as the process which the handler was registered by sigaction, isn't it?

    And you already did it... But I recomend you do this:
    Code:
    // Initialize sa_flags and sa_sigaction and ZERO anything else!
    struct sigaction sa = { .sa_flags = SA_SIGINFO, .sa_sigaction = handler_readPipeSIGIO };
    
    // and then register the handler.
    sigaction( SIGIO, &sa, NULL );

  6. #6
    Registered User
    Join Date
    Nov 2020
    Posts
    12
    Quote Originally Posted by Salem View Post
    Your code doesn't compile.
    strange

    my be i upload one of my attempts
    sorry

    try this

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
    #include <string.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <sys/wait.h>
    
    int const pipeCount = 1;
    int pipes[pipeCount][2];
    
    void handler_readPipeSIGIO(int sig, siginfo_t *info, void *secret) 
    {
    
        printf( "info->si_pid: %d\n",  info->si_pid);
    
        char buf[ 333 ];
        int ret = read(pipes[0][0], buf, sizeof( buf ));
        if ( ret < 0 ) 
        {
            printf( "Read fail! %d\n", sig);
            fflush(stdout);
        }
        else
        {
            buf[ ret ] = 0;
            printf( "Read data form Process: %s", buf );
            fflush(stdout);
        }
    
    }
    
    int main () 
    {
        // Create Pipes
        for(int i = 0; i<pipeCount; i++)
        {
            pipe(pipes[i]);
        }
    
        // Create Children
        for(int j = 0; j<pipeCount; j++)
        {
            if(fork()==0)
            {
            //CloseAllPipiesButTheOne
                for(int i=0; i<pipeCount; i++)
                {
                    close(pipes[i][0]);
                    //printf("Process %d Pipe %d End 0 is CLOSE\n", j, i);
                    if(j==i)
                    {
                        ///printf("Process %d Pipe %d End 1 is OPEN\n", j, i);
                        //printf("MyChildD %d \n", getpid());
                    }
                    else
                    {
                        //printf("Process %d Pipe %d End 1 is CLOSE\n", j, i);
                        close(pipes[i][1]);
                    }
                }
                //fflush(stdout);
                //Write data to 0 End of pipes ... 
                while ( 1 )
                {   
                    //printf("Writing to Pipe from Child - %d \n", getpid());
                    fflush(stdout);
                    char buf[ 333 ];
                    //sprintf( buf, "Pid: (%d) Random Number: %d\n", getpid(), rand() % 10000 );
                    sprintf( buf, "Pid: (%d)\n", getpid());
                    write( pipes[j][1], buf, strlen( buf ) );
                    sleep( 2 + rand() % 5 );
                }
                return 0;
            }
        }
    
        //close Pipes
        for(int i=0; i<pipeCount; i++)
        {
            close(pipes[i][1]);
        }
    
        //SigAction Define
    
        struct sigaction sa;
        sa.sa_sigaction = handler_readPipeSIGIO; 
        sa.sa_flags = SA_RESTART | SA_SIGINFO; 
        sigemptyset( &sa.sa_mask ); 
    
        sigaction(SIGIO, &sa, NULL);
    
        //config read reaction for SIGIO
    
        for(int i=0; i<pipeCount; i++)
        {
            fcntl( pipes[i][0], F_SETFL, fcntl( pipes[i][0], F_GETFL ) | O_ASYNC );
            fcntl( pipes[i][0], F_SETSIG, SIGIO );
            fcntl( pipes[i][0], F_SETOWN, getpid() );
        }
    
    
        printf("Some out ... \n");
        fflush(stdout);
        while(1) sleep (1);
        //wait(NULL);
        return(0);
    }

  7. #7
    Registered User
    Join Date
    Feb 2019
    Posts
    886
    Quote Originally Posted by Empair View Post
    So my questing is: How a get i PID of process witch calling a Handler?
    Didn't you mean how to get the PID of the process dispatching the signal? Because the PID of the process "calling" the handler will be the same as the process which the handler was registered by sigaction, isn't it?

    And you already did it... But I recomend you do this:
    Code:
    // Initialize sa_flags and sa_sigaction and ZERO anything else!
    struct sigaction sa = { .sa_flags = SA_SIGINFO, .sa_sigaction = handler_readPipeSIGIO };
    
    // and then register the handler.
    sigaction( SIGIO, &sa, NULL );
    And, as always, Salem is right. printf() family of functions aren't AS-Safe. You should use write() syscall and your own itoa() function (since it's not present anymore).

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,736
    Well it might compile, but you need to compile this 'C' code using a C++ compiler.
    So I made your 'const int' a #define instead.
    Code:
    $ g++ -D_GNU_SOURCE  -Wall main.c
    $ gcc -D_GNU_SOURCE  -Wall main.c
    main.c:11:5: error: variably modified ‘pipes’ at file scope
     int pipes[pipeCount][2];
         ^
    $ gcc -D_GNU_SOURCE  -Wall main.c
    The next problem is that si_pid isn't a unique data member, at least not on my system.
    Code:
    $ gcc -D_GNU_SOURCE -g -Wall main.c
    $ gdb -q ./a.out
    Reading symbols from ./a.out...done.
    (gdb) b handler_readPipeSIGIO 
    Breakpoint 1 at 0x400a25: file main.c, line 14.
    (gdb) run
    Starting program: ./a.out 
    
    Breakpoint 1, handler_readPipeSIGIO (sig=29, info=0x7fffffffd5b0, secret=0x7fffffffd480) at main.c:14
    14	{
    (gdb) p *info
    $1 = {si_signo = 29, si_errno = 0, si_code = 1, _sifields = {_pad = {65, 0, 3, 0, 0, 0, -136507304, 32767, -9600, 32767, -134229952, 32767, 0, 0, 0, 0, 1024, 0, -136418554, 32767, 1, 0, 
          0, 0, 404, 0, -136481568, 32767}, _kill = {si_pid = 65, si_uid = 0}, _timer = {si_tid = 65, si_overrun = 0, si_sigval = {sival_int = 3, sival_ptr = 0x3}}, _rt = {si_pid = 65, 
          si_uid = 0, si_sigval = {sival_int = 3, sival_ptr = 0x3}}, _sigchld = {si_pid = 65, si_uid = 0, si_status = 3, si_utime = 0, si_stime = 140737351848024}, _sigfault = {
          si_addr = 0x41, si_addr_lsb = 3, si_addr_bnd = {_lower = 0x0, _upper = 0x7ffff7dd1058}}, _sigpoll = {si_band = 65, si_fd = 3}, _sigsys = {_call_addr = 0x41, _syscall = 3, 
          _arch = 0}}}
    (gdb) ptype info
    type = struct {
        int si_signo;
        int si_errno;
        int si_code;
        union {
            int _pad[28];
            struct {...} _kill;
            struct {...} _timer;
            struct {...} _rt;
            struct {...} _sigchld;
            struct {...} _sigfault;
            struct {...} _sigpoll;
            struct {...} _sigsys;
        } _sifields;
    } *
    You need to use si_code to figure out which union member of _sifields to go looking in.

    Not that it would help much in your case, but it doesn't look like there is anything resembling the pid of the signalling process in the struct in any of the union variants.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. create a child process that creates a child process
    By cus in forum Linux Programming
    Replies: 9
    Last Post: 01-13-2009, 02:14 PM
  2. Child process status
    By paraglidersd in forum C Programming
    Replies: 8
    Last Post: 07-24-2008, 10:51 AM
  3. Child process I/O
    By madmardigan53 in forum Windows Programming
    Replies: 6
    Last Post: 08-23-2004, 10:40 PM
  4. Child Process & Parent Process Data :: Win32
    By kuphryn in forum Windows Programming
    Replies: 5
    Last Post: 09-11-2002, 12:19 PM
  5. child process
    By Unregistered in forum C Programming
    Replies: 4
    Last Post: 07-31-2002, 03:45 PM

Tags for this Thread