- проблема с ptrace, NuINu, 20:45 , 15-Ноя-08 (1)
>При трассировке дочернего процесса с помощью ptrace, если дочерний процесс завершается из-за >сигнала SIGSEGV, то в родительском процессе WIFSIGNALED(wait_val) возвращает 0. >Если ptrace не использовать, а просто запустить дочерний процесс, то сигнал нормально >определяется. В чем тут дело? как ты получил wait_val? если процесс не завершился там ничего и не будет. в общем без кода ничего сказать нельзя!
- проблема с ptrace, Merloc, 13:00 , 16-Ноя-08 (2)
Вот код: 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; }А вообще мне нужно если программа завершилась сохранить значения ее регистров и последний фрейм стека. если кто знает как это сделать, то пожалуйста подскажите.
- проблема с ptrace, Merloc, 13:02 , 16-Ноя-08 (3)
>А вообще мне нужно если программа завершилась сохранить значения ее регистров и >последний фрейм стека.Я хотел сказать если программа завершилась с ощибкой.
- проблема с ptrace, NuINu, 21:24 , 16-Ноя-08 (4)
>>А вообще мне нужно если программа завершилась сохранить значения ее регистров и >>последний фрейм стека. > >Я хотел сказать если программа завершилась с ощибкой. это кончено не моя тема, ну вот что я написал полазив в инете и посмотрев твою программу, это небольшая демка приблизительно показывающая как ведет себе процесс. #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 ну и ман.
- проблема с ptrace, Merloc, 15:42 , 17-Ноя-08 (5)
Спасибо. Теперь у меня появился такой вопрос: Если процесс не рушится и продолжает работать нормально (например openoffice writer открыл документ), то как определить когда он уже открыл документ (или что-либо сделал) и его можно убить ( kill(SIGKILL))?
- проблема с ptrace, NuINu, 16:35 , 17-Ноя-08 (6)
>Спасибо. >Теперь у меня появился такой вопрос: >Если процесс не рушится и продолжает работать нормально (например openoffice writer открыл >документ), то как определить когда он уже открыл документ (или что-либо >сделал) и его можно убить ( kill(SIGKILL))? А зачем убивать офис когда он открыл документ? если очень интересно поотлаживать посмотри исходники strace думаю там все есть.
- проблема с ptrace, vic, 16:54 , 17-Ноя-08 (7)
> >А зачем убивать офис когда он открыл документ? За то что открыл =)) >>сделал) и его можно убить ( kill(SIGKILL))? Sigkill это последнее средство, крайне "грубое", у процесса не будет не единого шанса на последнее желание :) Если надо сообщить процессу что пора завершится, то следует использовать другие сигналы или внешние команды, какие конкретные это надо смотреть доку по запускаемому приложению. Если разработчики не удосужились реализовать подобный механизм, то все равно лучше уж sigterm (по умолчанию завершает приложение), чем sigkill, sigkill используется если исчерпаны все средства убеждения :)
|