Ошибка с обработкой сигналов для процессов в Linux - PullRequest
0 голосов
/ 17 ноября 2010

Ниже приведен фрагмент кода:

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

sig_atomic_t child1 ;

sig_atomic_t child2 ;

void child1_handler( int sig_num )
{

     int ret ;

 if(sig_num == SIGUSR2 )
 {
    printf("\n Recieved sigusr2 for child1\n");

    ret = kill( getppid() , SIGUSR2 ) ;
    if( ret != 0 )

        kill( getpid() , SIGTERM );
 }
 else if(sig_num == SIGUSR1 )
 { 
    /* child 1 does something */
    printf("\n Recieved sigusr1 for child1\n");
    printf("\n child 1 is doing \n");

    kill( child2 , SIGUSR2 );
 }
}

void child2_handler( int sig_num )
{
if( sig_num == SIGUSR2 )
{
    /* child2 does somethign */
    printf("\n Recieved sigusr2 for child2\n");
    printf("\n child2 is doing \n");

    kill( child1 , SIGUSR2 );

    kill( getpid() , SIGTERM );
}
 }

 void parent_handler( int sig_num )
 {
int ret ;
if( sig_num == SIGUSR2 )
{
    printf("\n Recieved sigusr2 for parent\n");

    ret = kill( child1 , SIGUSR1 ) ;
    if( ret != 0 )
    {
        /* parent does something */

        printf( "\n Parent does something \n" );
        exit(0);
    }
}
   }


   int main()
   {
struct sigaction sa_parent , sa_child1 , sa_child2 ;
pid_t temp_id1 , temp_id2 ;
int temp ;

memset(&sa_parent , 0 , sizeof(sa_parent) ) ;
memset(&sa_child1 , 0 , sizeof(sa_child1) ) ;
memset(&sa_child2 , 0 , sizeof(sa_child2) ) ;

/* parent */

printf( " \n Inside parent \n" );

sa_parent.sa_handler = &parent_handler ;
sigaction( SIGUSR2 , &sa_parent , NULL );

temp_id1 = fork() ;

if( temp_id1 == 0 )
{
    child1 = getpid() ;

    /* child1 */

    printf("\n inside child1 \n" );

    sa_child1.sa_handler = &child1_handler ;    
    sigaction( SIGUSR1 , &sa_child1 , NULL ) ;
    sigaction( SIGUSR2 , &sa_child1 , NULL ) ;

    temp_id2 = fork() ;

    if( temp_id2 == 0 )
    {
        child2 = getpid() ;

        /* child2 */

        printf( "\n inside child2 \n" );

        sa_child2.sa_handler = &child2_handler ;
        sigaction( SIGUSR2 , &sa_child2 , NULL );

        kill( child1 , SIGUSR2 );
    }

    wait(&temp);
}

wait(&temp);
return 0 ;
   }

Я ожидаю, что на выходе будет отображаться этот первый

child1 is doing
child2 is doing
parent does something 

Однако полученная продукция соответствует приведенной ниже.

Inside parent 
inside child1 
inside child2 
Recieved sigusr2 for child1
Recieved sigusr2 for parent
Recieved sigusr1 for child1
child 1 is doing 
Recieved sigusr2 for child1
User defined signal 1

[ what is going wrong ? ]

Пожалуйста, игнорируйте строки "полученный знак" и "Внутри ...", так как они должны были отмечать места в коде.

Ответы [ 2 ]

1 голос
/ 17 ноября 2010

Переменная child1 не установлена ​​в родительском процессе.Следовательно, вызов kill() в родительском элементе будет сигнализировать обо всех процессах в текущей группе процессов.

Кроме того, использование printf() в обработчике сигналов редко безопасно.Здесь это кажется почти безопасным, потому что прерванная функция - wait(), которая безопасна для асинхронного сигнала, но в целом небезопасна.

waitpid() или wait4() предпочтительнее wait(), поскольку ониждать определенного дочернего процесса.

0 голосов
/ 17 ноября 2010

Адресные пространства трех процессов никоим образом не разделяются. Таким образом, переменные child1 и child2 различаются между процессами. Поэтому, когда первый дочерний элемент устанавливает значение child1, это не влияет на переменную child1 в родительском элементе. Поэтому, когда родитель отправляет сигнал «child1», он отправляется 0 - всей группе процессов.

...