WIFSIGNALED возвращает false, даже если я отправляю сигнал с командой kill в Linux (Mint 18.3) - PullRequest
0 голосов
/ 14 сентября 2018

Проблема: Мне нужно напечатать сигнал уничтожения, полученный процессом,

Для Пример :

Если я отправлю *kill -15 1245*, где 1245 - pid моего процесса, моя программа должна напечатать что-то вроде "Process killed by signal 15", но даже если я отправлю *kill -15* напроцесс WIFSIGNALED macro returns false and obviously WTERMSIG returns 0.

Система: Я работаю на Linux Mint 18.3, дистрибутиве на основе Ubuntu, и я тестировал свою программу в других дистрибутивах Ubuntu ивсе еще не работает, НО в Fedora и OpenSUSE это работает хорошо.Есть идеи?

Код:

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

//Macros
#define MAX_LIMIT 50

//Function where i create a child process and execute a shell over it.
void run(char comando[])
{
    int status;
    pid_t pid;
    if((pid = fork()) == 0)
        execlp("sh", "sh", "-c", comando, NULL);
    pid = waitpid(pid, &status, 0);
    //The problem begins here, the WIFEXITED returns *true* even is the process was killed by a signal.
    if(WIFEXITED(status))
        printf("Process ended with status %d\n", 
WEXITSTATUS(status));
    //Is here when i need to print the signal, but WIFSIGNALED returns *false* even if a signal was sended by the *kill* command.
    else if(WIFSIGNALED(status))
        printf("Process killed by signal %d\n", 
WTERMSIG(status));
    else if(WIFSTOPPED(status))
        printf("Process stopped by signal %d\n", 
WSTOPSIG(status));
    else if(WIFCONTINUED(status))
        printf("Process continued...\n");
} 
//Function that simulates a shell by repeating prompt.
void shell()
{
    run("clear");
    printf("\t\t\t\t\tMINI_SHELL\n");
    char comando[MAX_LIMIT];
    do
    {
        printf("$> ");
        fgets(comando, MAX_LIMIT, stdin);
        char *cp = strchr(comando,'\n'); if (cp != NULL) *cp =  0;
        if(strcmp(comando, "ext") != 0)
            run(comando);
    } while(strcmp(comando, "ext") != 0);
}

int main(int argc, char *argv[])
{
    shell();
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 15 сентября 2018

Примечание: Это предваряется верхними комментариями.

Поскольку fgets оставляет \n в конце, его следует удалить перед передачей в execlp.В противном случае команда, скорее всего, потерпит неудачу [быстро] (со статусом WIFEXITED) из-за того, что не будет найдена команда, в конце которой находится символ новой строки.Чтобы удалить это, после fgets добавьте:

char *cp = strchr(comando, '\n');
if (cp != NULL)
    *cp = 0;

В Fedora /bin/sh является символической ссылкой на /bin/bash.Под Ubuntu sh может быть символически связан с чем-то другим.Могут существовать различия в интерпретации оболочек и в том, как они устанавливают маску сигналов по умолчанию перед вызовом целевой команды.

Поскольку Fedora работает правильно, для обеспечения согласованности замените sh в вашем execlp на bash.Это должно заставить оба дистрибутива вести себя одинаково.

0 голосов
/ 14 сентября 2018

Все сводится к разнице между оболочкой по умолчанию в дистрибутивах на основе Debian (/bin/dash) и в дистрибутивах на основе redhat (/bin/bash).

Когда вы звоните

execlp("sh", "sh", "-c", comando, NULL);

с commando, как "cat" или "echo 1; cat", если sh равно /bin/dash (как в Debian), оболочка сама вызовет waitpid() для статуса cat довыход;если sh равен /bin/bash, он просто exec до последней команды в сценарии.

Попробуйте ввести команду типа echo pid=$$; cat в вашей мини-оболочке, затем kill pidнапечатанный эхом, а не pid cat, и вы получите ожидаемый «процесс уничтожен сигналом ...»

...