The OpenNET Project / Index page

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




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
проблема с ptrace, !*! Merloc, 15-Ноя-08, 16:52  [смотреть все]
При трассировке дочернего процесса с помощью ptrace, если дочерний процесс завершается из-за сигнала SIGSEGV, то в родительском процессе WIFSIGNALED(wait_val) возвращает 0.
Если ptrace не использовать, а просто запустить дочерний процесс, то сигнал нормально определяется. В чем тут дело?
  • проблема с 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 используется если исчерпаны все средства убеждения :)




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

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