The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  вход/выход  слежка  RSS
"проблема с ptrace"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [ Отслеживать ]

"проблема с ptrace"  
Сообщение от Merloc on 15-Ноя-08, 16:52 
При трассировке дочернего процесса с помощью ptrace, если дочерний процесс завершается из-за сигнала SIGSEGV, то в родительском процессе WIFSIGNALED(wait_val) возвращает 0.
Если ptrace не использовать, а просто запустить дочерний процесс, то сигнал нормально определяется. В чем тут дело?
Высказать мнение | Ответить | Правка | Cообщить модератору

 Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "проблема с ptrace"  
Сообщение от NuINu (??) on 15-Ноя-08, 20:45 
>При трассировке дочернего процесса с помощью ptrace, если дочерний процесс завершается из-за
>сигнала SIGSEGV, то в родительском процессе WIFSIGNALED(wait_val) возвращает 0.
>Если ptrace не использовать, а просто запустить дочерний процесс, то сигнал нормально
>определяется. В чем тут дело?

как ты получил wait_val? если процесс не завершился там ничего и не будет.
в общем без кода ничего сказать нельзя!

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

2. "проблема с ptrace"  
Сообщение от Merloc on 16-Ноя-08, 13:00 
Вот код:
int main(void)
{
    int wait_val;
    int pid;
    struct user_regs_struct regs = {0};
    switch (pid = fork()) {
    case -1:
        perror("fork");
        break;
    case 0: /*  запуск дочернего процесса        */
        ptrace(PTRACE_TRACEME, 0, 0, 0);
        execl("/home/merloc/test", "test", "aaaaaaaaaaaa", NULL);
        break;
    default:
        if(wait(&wait_val) == -1)
            printf("wait error: %s\n", strerror(errno));
        if(ptrace(PTRACE_CONT, pid, 0, 0) != 0)
            printf("ptrace error: %s\n", strerror(errno));        
        if(wait(&wait_val) == -1)
                        printf("wait error: %s\n", strerror(errno));
        if(WIFSIGNALED(wait_val))
        {
               if(ptrace(PTRACE_GETREGS, pid, NULL, ®s) != 0)
                printf("ptrace error: %s\n", strerror(errno));
               else
                printregs(®s);
        }
        break;
    }
    return 0;
}

А вообще мне нужно если программа завершилась сохранить значения ее регистров и последний фрейм стека. если кто знает как это сделать, то пожалуйста подскажите.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

3. "проблема с ptrace"  
Сообщение от Merloc on 16-Ноя-08, 13:02 
>А вообще мне нужно если программа завершилась сохранить значения ее регистров и
>последний фрейм стека.

Я хотел сказать если программа завершилась с ощибкой.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

4. "проблема с ptrace"  
Сообщение от NuINu (??) on 16-Ноя-08, 21:24 
>>А вообще мне нужно если программа завершилась сохранить значения ее регистров и
>>последний фрейм стека.
>
>Я хотел сказать если программа завершилась с ощибкой.

это кончено не моя тема, ну вот что я написал полазив в инете и посмотрев твою программу, это небольшая демка приблизительно показывающая как ведет себе процесс.

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <errno.h>
#include <signal.h>
#include <linux/user.h>

int chld_count;

void analize_status(pid_t pid, int status) {
    printf("Analize return code(%i) process pid = %u\n", status, pid);
    if(WIFEXITED(status)) {
    fprintf(stdout, "Child process exited normally!\n");
    }
    if(WIFSIGNALED(status)) {
    fprintf(stdout, "Child process terminated by signal %d!\n",WTERMSIG(status));
    }
    if(WIFSTOPPED(status)) {
    fprintf(stdout, "waitpid() return - child STOPED!!!\n");
    } else {
    fprintf(stdout, "waitpid() return - child not stoped!!!\n");
    }
}

void printregs(struct user_regs_struct *regs) {
    fprintf(stdout, "Registers status:\n"
    " eax=0x%08lX esi=0x%08lX ds=0x%04X\n"
    " ebx=0x%08lX edi=0x%08lX es=0x%04X\n"
    " ecx=0x%08lX esp=0x%08lX ebp=0x%08lX ss=0x%04X\n"
    " edx=0x%08lX eip=0x%08lX cs=0x%04X\n"
    " eflags=0x%08lX, orig_eax=0x%08lX\n",
    regs->ax, regs->si, (int)regs->ds,
    regs->bx, regs->di, (int)regs->es,
    regs->cx, regs->sp, regs->bp, (int)regs->ss,
    regs->dx, regs->ip, (int)regs->cs,
    regs->flags, regs->orig_ax);    

}

void child_handler(int signo) {
    printf("Main: get child signal %i\n", signo);
    pid_t pid;
    int status;
    int i;
    struct user_regs_struct regs;

    while((pid = waitpid(-1, &status, WNOHANG)) > 0) {
    printf("signal: pid: %i\n", pid);
    analize_status(pid, status);
        if(ptrace(PTRACE_GETREGS, pid, NULL, ®s) != 0)
            printf("ptrace error: %s\n", strerror(errno));
        else
            printregs(®s);

    chld_count--;
    }
}


int main(int argc, char *argv[])
{
    int wait_val;
    int status;
    pid_t pid;
    struct user_regs_struct regs;
    switch (pid = fork()) {
    case -1:
        perror("fork");
        break;
    case 0:   /*  запуск дочернего процесса        */
        printf("Child: Before start trace!\n");
        ptrace(PTRACE_TRACEME, 0, 0, 0);
        printf("Child: After start trace!\n");
        execl("test_wait_sig2", "test_wait_sig", "aaaaaaaaaaaa", NULL);
        break;
    default: /* РОДИТЕЛЬСКИЙ ПРОЦЕСС               */
    printf("Run child pid: %u\n", pid);
    chld_count = 1;
    //подождем первого сигнала от дочернего процесса
    waitpid(pid, &status, 0);
    analize_status(pid, status);
    //Запускаем трассируемый процесс без всякий условий (пусть выполняется).
    //ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
    ptrace(PTRACE_CONT, pid, 0, 0);
    //сами засыпаем секунд на 5
        printf("Parent: sleeping ......\n");
    sleep(5);
    //шлем сигнал процессу child
        printf("Parent: Killed child!\n");
    kill(pid, SIGSEGV);
    
    //снова ждем остановки дочернего процесса
    waitpid(pid, &status, 0);
    //возврат просто от того что ребенок остановился?
    printf("Parent: retun from wait success(%i)\n", status);
    analize_status(pid, status);
    
    //НЕТ ребенок получил какой то сигнал!!! и его не обработал, вернем его ему!(мы то знаем что за сигнал он поулчил)
    if (ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACEEXIT) != 0) {
            perror("ptrace: error set option PTRACE_O_TRACEEXIT\n");
    }
    if (ptrace(PTRACE_CONT, pid, 0, SIGSEGV) != 0) {
            perror("ptrace: error PTRACE_CONT");
    }
    //дождемся останова! это должна быть функция exit
    waitpid(pid, &status, 0);
    analize_status(pid, status);

    if(ptrace(PTRACE_GETREGS, pid, NULL, ®s) != 0)
            printf("ptrace error PTRACE_GETREGS: %s\n", strerror(errno));
    else
            printregs(®s);
    break;
    }
        //установим обработчик завершения дочернего процесса
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = &child_handler;
    sigaction(SIGCHLD, &sa, NULL);
    
    if (ptrace(PTRACE_CONT, pid, 0, SIGSEGV) != 0) {
        perror("ptrace: error last run child PTRACE_O_TRACEEXIT!\n");
    }

    while(chld_count > 0 ) {
        sleep(2);
        printf("Parent: wait any kill - child please!!!\n");
    }

    return 0;
}

вот что она мне выдала:
Run child pid: 3324
Child: Before start trace!
Child: After start trace!
Analize return code(1407) process pid = 3324
waitpid() return - child STOPED!!!
Parent: sleeping ......
run child process 3324
run child process 3324
run child process 3324
run child process 3324
run child process 3324
Parent: Killed child!
Parent: retun from wait success(2943)
Analize return code(2943) process pid = 3324
waitpid() return - child STOPED!!!
Analize return code(394623) process pid = 3324
waitpid() return - child STOPED!!!
Registers status:
eax=0x00000033 esi=0x00000073 ds=0xBFF95188
ebx=0xBFD27EF8 edi=0x00200246 es=0x80484E8
ecx=0x000000A2 esp=0xBFF96422 ebp=0x00000000 ss=0xB7F71FBE
edx=0xB7F2F77B eip=0x0000007B cs=0x0001
eflags=0x00000000, orig_eax=0xBFD27D30
Main: get child signal 17
signal: pid: 3324
Analize return code(11) process pid = 3324
Child process terminated by signal 11!
waitpid() return - child not stoped!!!
ptrace error: No such process
Parent: wait any kill - child please!!!
--------------------------------------------------
смысл такой что сигнал в трассируемый процесс не передается непосредственно, а при получении сигнала этот процесс останавливается и управление передается трассирующему процессу. а если мы хотим что бы этот сигнал обработался надо его самостоятельно передать в трассируемый процесс. да если чилд обрабатывает сигнал, то на ретурн код будет 0.т.е если в нем установить обработчик этого сигнала.

что я смотрел:
http://www.dore.ru/perl/nntp.pl?f=1&gid=22&mid=16862
http://gazette.linux.ru.net/lg81/sandeep.html
ну и ман.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

5. "проблема с ptrace"  
Сообщение от Merloc on 17-Ноя-08, 15:42 
Спасибо.
Теперь у меня появился такой вопрос:
Если процесс не рушится и продолжает работать нормально (например openoffice writer открыл документ), то как определить когда он уже открыл документ (или что-либо сделал) и его можно убить ( kill(SIGKILL))?
Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

6. "проблема с ptrace"  
Сообщение от NuINu (??) on 17-Ноя-08, 16:35 
>Спасибо.
>Теперь у меня появился такой вопрос:
>Если процесс не рушится и продолжает работать нормально (например openoffice writer открыл
>документ), то как определить когда он уже открыл документ (или что-либо
>сделал) и его можно убить ( kill(SIGKILL))?

А зачем убивать офис когда он открыл документ?

если очень интересно поотлаживать посмотри исходники strace думаю там все есть.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

7. "проблема с ptrace"  
Сообщение от vic (??) on 17-Ноя-08, 16:54 
>
>А зачем убивать офис когда он открыл документ?

За то что открыл =))

>>сделал) и его можно убить ( kill(SIGKILL))?

Sigkill это последнее средство, крайне "грубое", у процесса не будет не единого шанса на последнее желание :)
Если надо сообщить процессу что пора завершится, то следует использовать другие сигналы или внешние команды, какие конкретные это надо смотреть доку по запускаемому приложению. Если разработчики не удосужились реализовать подобный механизм, то все равно лучше уж sigterm (по умолчанию завершает приложение), чем sigkill, sigkill используется если исчерпаны все средства убеждения :)

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ] [Рекомендовать для помещения в FAQ]




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру