2015-11-07 1 views
1

Я изучаю сигналы и процессы на Linux (Ubuntu) и писать простые программы на C.Отправка сигнал родительского процесса с убийством регистрирует меня

Вот код.

#define _XOPEN_SOURCE 500 
#include <ftw.h> 
#define MAXFD 20 
#include <unistd.h> 
#include <stdio.h> // standard input/output 
#include <stdlib.h> 
#include <string.h> // string operations 
#include <dirent.h> // dirent 
#include <sys/stat.h> // filestat 
#include <errno.h> // errno 
#include <time.h> 
#include <sys/time.h> 
#include <sys/wait.h> 
#include <fcntl.h> 
#include <signal.h> 

#define ERR(source) (perror(source),\ 
        fprintf(stderr,"%s:%d\n",__FILE__,__LINE__),\ 
        kill(0,SIGKILL),\ 
        exit(EXIT_FAILURE)) 

volatile sig_atomic_t last_signal = 0; 
int sig_count=0; 

void usage(char *name){ 
    fprintf(stderr,"USAGE: %s t \n",name); 
    fprintf(stderr,"t - how often send SIGUSR1 signals\n"); 
    exit(EXIT_FAILURE); 
} 

void sethandler(void(*f)(int),int sigNo){ 
    struct sigaction act; 
    memset(&act,0,sizeof(struct sigaction)); 
    act.sa_handler = f; 
    if (-1==sigaction(sigNo,&act,NULL)) ERR ("sigaction"); 
} 

void countSigHandler(int sig){ 
    sig_count++; 
    printf("Parent received a total of %d SIGUSR2\n",sig_count); 
} 

void sigchld_handler(int sig) { 
     pid_t pid; 
     for(;;){ 
       pid=waitpid(0, NULL, WNOHANG); 
       if(pid==0) return; 
       if(pid<=0) { 
         if(errno==ECHILD) return; 
         ERR("waitpid"); 
       } 
     } 
} 

void child_work(int t){ 
    struct timespec ts = {0,t}; 
    int i=0; 
    sethandler(SIG_DFL,SIGUSR1); 
    for (i=0;i<10;i++){ 
     //nanosleep(&ts,NULL); 
     sleep(t); 
     if (kill(getppid(),SIGUSR1)) ERR("kill"); 
     //if (kill(getppid(),SIGUSR1)) ERR("kill"); 
     printf("[%d] sending SIGUSR1 to %d\n",getpid(),getppid()); 
    } 
} 

void parent_work(){ 
    return; 
} 

int main(int argc, char** argv) { 
     int t; 
     t = atoi(argv[1]); 

     sethandler(sigchld_handler,SIGCHLD); 
     sethandler(countSigHandler,SIGUSR1);  

     pid_t pid; 
     if ((pid=fork())==-1)ERR("fork"); 

     if (pid==0) child_work(t); 
     else { 
      if (kill(0,SIGUSR1)) ERR("kill"); 
      //parent_work(); 
      //while(wait(NULL)>0); 
     } 
     return EXIT_SUCCESS; 
} 

Когда я запускаю его из терминала (скомпилированный файл) с на 1, он записывает меня, и я должен ввести свой пароль еще раз, чтобы войти (и все программы закрыты, когда я снова войти в систему).

Если я прокомментирую строку в child_work, которая использует kill для отправки сигнала, она работает нормально.

Что здесь происходит? Вы можете мне помочь?

+1

Почему вы называете kill с pid 0? – fuz

+0

Этот сигнал просто посылает сигнал всем процессам данной группы. И это не вызывает никаких сбоев. – Greyshack

+0

Вы уверены? Потому что, когда вы запускаете процесс в своей оболочке, он находится в той же группе процессов, что и ваша оболочка, и, возможно, весь ваш сеанс. Поскольку 'SIGUSR1' имеет стандартное расположение« завершение программы », это приведет к уничтожению всех процессов в той же группе процессов, которые должны учитывать симптом, который вы видите. – fuz

ответ

1

Я думаю, что получил. Я изменил код, чтобы удалить все удары, но добавил отпечатки PID. Вот последовательность при^= 0:

I am 12684 
pgid=12684 // I printed the PGID to be sure 
[12685] sending SIGUSR1 to 12684 
[12685] sending SIGUSR1 to 11451 
(…) // same line repeated, from the for loop 

С т = 1 это непосредственно 11451. Вы были правы, потому что на моем процессе сеанса с PID 11451 является:

init --user 

начал как мой пользователь , Поэтому мне разрешено посылать на него сигналы. И так да, после смерти отца ребенок привязан к init, вот «мой» init, и поэтому getppid() указывает на него, и код убивает init!

Если вы повторно активируете цикл wait(), выходной результат отличается, поскольку я вижу только ПИД-код отца (конечно, без реального убийства отец все еще жив).

Не уверен, почему этот «закрытый» init используется (не следует последним изменениям в Ubuntu). Зная это и предотвращая такое поведение, я предлагаю хранить PID при запуске процесса (перед любыми вилками) и использовать это сохраненное значение после этого у детей. Таким образом, вы обязательно «убиваете» правильную цель или убиваете кого-либо, если отец умирает по какой-либо причине.

 Смежные вопросы

  • Нет связанных вопросов^_^