Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 9240 in orxonox.OLD for trunk/src/util


Ignore:
Timestamp:
Jul 6, 2006, 12:25:44 PM (18 years ago)
Author:
bensch
Message:

orxonox/trunk: better signal handler.
patched by chrigi

Location:
trunk/src/util
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/util/signal_handler.cc

    r8293 r9240  
    2121#ifndef __WIN32__
    2222
     23#include <wait.h>
     24
    2325SignalHandler::SignalHandler()
    2426{
    2527}
    2628
    27 void SignalHandler::doCatch( std::string appName, GdbRunType type )
    28 {
    29   this->type = type;
     29void SignalHandler::doCatch( std::string appName )
     30{
    3031  this->appName = appName;
    3132
     
    7778
    7879  printf( "recieved signal %s\ntry to write backtrace to file orxonox.backtrace\n", sigName.c_str() );
    79 
    80   int fd[2];
    81 
    82   assert( pipe(fd) != -1 );
    83 
    84   int pid = fork();
    85 
    86   assert( pid != -1 );
    87 
    88 
    89   if ( pid == 0 )
     80 
     81  int sigPipe[2];
     82  if ( pipe(sigPipe) == -1 )
     83  {
     84    perror("pipe failed!\n");
     85    exit(EXIT_FAILURE);
     86  }
     87 
     88  int sigPid = fork();
     89
     90  if ( sigPid == -1 )
     91  {
     92    perror("fork failed!\n");
     93    exit(EXIT_FAILURE);
     94  }
     95
     96  // gdb will be attached to this process
     97  if ( sigPid == 0 )
    9098  {
    9199    getInstance()->dontCatch();
    92     sleep(2);
     100    // wait for message from parent when it has attached gdb
     101    int someData;
     102
     103    read( sigPipe[0], &someData, sizeof(someData) );
     104
     105    if ( someData != 0x12345678 )
     106    {
     107      printf("something went wrong :(\n");
     108    }
    93109
    94110    return;
    95111  }
    96   else
    97   {
    98     getInstance()->dontCatch();
    99     if ( getInstance()->type == GDB_RUN_WRITE_TO_FILE && fork() == 0 )
    100     {
    101       sleep(1);
    102       write( fd[1], "c\nbt\nq\n", 7 );
    103 
    104       exit(0);
    105     }
    106 
    107     char command[256];
    108     if ( getInstance()->type == GDB_RUN_WRITE_TO_FILE )
    109     {
    110       dup2( fd[0], STDIN_FILENO );
    111       snprintf( command, 255, "gdb -p %d %s 1>>" GDB_BT_FILE " 2>&1", pid, getInstance()->appName.c_str() );
    112     }
    113     else
    114       snprintf( command, 255, "gdb -p %d %s", pid, getInstance()->appName.c_str() );
    115     execlp( "sh", "sh", "-c", command, (void*)NULL);
    116   }
     112
     113  int gdbIn[2];
     114  int gdbOut[2];
     115  int gdbErr[2];
     116 
     117  if ( pipe(gdbIn) == -1 || pipe(gdbOut) == -1 || pipe(gdbErr) == -1 )
     118  {
     119    perror("pipe failed!\n");
     120    kill( sigPid, SIGTERM );
     121    waitpid( sigPid, NULL, 0 );
     122    exit(EXIT_FAILURE);
     123  }
     124
     125  int gdbPid = fork();
     126  // this process will run gdb
     127 
     128  if ( gdbPid == -1 )
     129  {
     130    perror("fork failed\n");
     131    kill( sigPid, SIGTERM );
     132    waitpid( sigPid, NULL, 0 );
     133    exit(EXIT_FAILURE);
     134  }
     135 
     136  if ( gdbPid == 0 )
     137  {
     138    // start gdb
     139   
     140    close(gdbIn[1]);
     141    close(gdbOut[0]);
     142    close(gdbErr[0]);
     143
     144    dup2( gdbIn[0], STDIN_FILENO );
     145    dup2( gdbOut[1], STDOUT_FILENO );
     146    dup2( gdbErr[1], STDERR_FILENO );
     147   
     148    execlp( "sh", "sh", "-c", "gdb", (void*)NULL);
     149  }
     150
     151  char cmd[256];
     152  snprintf( cmd, 256, "file %s\nattach %d\nc\n", getInstance()->appName.c_str(), sigPid );
     153  write( gdbIn[1], cmd, strlen(cmd) );
     154
     155  int charsFound = 0;
     156  int promptFound = 0;
     157  char byte;
     158  while ( read( gdbOut[0], &byte, 1 ) == 1 )
     159  {
     160    if (
     161      charsFound == 0 && byte == '(' ||
     162      charsFound == 1 && byte == 'g' ||
     163      charsFound == 2 && byte == 'd' ||
     164      charsFound == 3 && byte == 'b' ||
     165      charsFound == 4 && byte == ')' ||
     166      charsFound == 5 && byte == ' '
     167        )
     168          charsFound++;
     169
     170    if ( charsFound == 6 )
     171    {
     172      promptFound++;
     173      charsFound = 0;
     174    }
     175
     176    if ( promptFound == 3 )
     177    {
     178      break;
     179    }
     180  }
     181 
     182  int someData = 0x12345678;
     183  write( sigPipe[1], &someData, sizeof(someData) );
     184
     185  write( gdbIn[1], "bt\nq\n", 5 );
     186
     187 
     188  charsFound = 0;
     189  promptFound = 0;
     190  std::string bt;
     191  while ( read( gdbOut[0], &byte, 1 ) == 1 )
     192  {
     193    bt += std::string( &byte, 1 );
     194
     195    if (
     196      charsFound == 0 && byte == '(' ||
     197      charsFound == 1 && byte == 'g' ||
     198      charsFound == 2 && byte == 'd' ||
     199      charsFound == 3 && byte == 'b' ||
     200      charsFound == 4 && byte == ')' ||
     201      charsFound == 5 && byte == ' '
     202        )
     203          charsFound++;
     204
     205    if ( charsFound == 6 )
     206    {
     207      promptFound++;
     208      charsFound = 0;
     209      bt += "\n";
     210    }
     211
     212    if ( promptFound == 2 )
     213    {
     214      break;
     215    }
     216  }
     217
     218
     219  waitpid( sigPid, NULL, 0 );
     220  waitpid( gdbPid, NULL, 0 );
     221 
     222  int wsRemoved = 0;
     223
     224  while ( wsRemoved < 2 && bt.length() > 0 )
     225  {
     226    if ( bt[1] == '\n' )
     227      wsRemoved++;
     228    bt.erase(0, 1);
     229  }
     230
     231  if ( bt.length() > 0 )
     232    bt.erase(0, 1);
     233
     234  time_t now = time(NULL);
     235
     236  std::string timeString = "\n\n\n\n"
     237                           "=======================================================\n"
     238                           "= time: " + std::string(ctime(&now)) +
     239                           "=======================================================\n";
     240  bt.insert(0, timeString);
     241 
     242  FILE * f = fopen( GDB_BT_FILE, "a" );
     243
     244  if ( !f )
     245  {
     246    perror("could not append to " GDB_BT_FILE);
     247    exit(EXIT_FAILURE);
     248  }
     249
     250  if ( fwrite( bt.c_str(), 1, bt.length(), f ) != bt.length() )
     251  {
     252    printf("could not write %d byte to " GDB_BT_FILE, bt.length());
     253    exit(EXIT_FAILURE);
     254  }
     255
     256  exit(EXIT_FAILURE);
    117257}
    118258
  • trunk/src/util/signal_handler.h

    r9110 r9240  
    1212
    1313#define GDB_BT_FILE "orxonox.backtrace"
    14 enum GdbRunType{
    15   GDB_RUN_WRITE_TO_FILE = 1,
    16   GDB_RUN_IN_FOREGROUND
    17 };
    1814
    1915typedef int (*SignalCallback)( void * someData );
     
    4844    void registerCallback( SignalCallback cb, void * someData );
    4945
    50     void doCatch( std::string appName, GdbRunType type = GDB_RUN_WRITE_TO_FILE );
     46    void doCatch( std::string appName );
    5147    void dontCatch();
    5248
     
    6157    static SignalHandler * singletonRef;
    6258
    63     GdbRunType type;
    64 
    6559    std::string appName;
    6660};
     
    7165 public:
    7266   inline static SignalHandler* getInstance() { if (!SignalHandler::singletonRef) SignalHandler::singletonRef = new SignalHandler(); return SignalHandler::singletonRef; };
    73   void doCatch( std::string appName, GdbRunType type = GDB_RUN_WRITE_TO_FILE ) {};
     67  void doCatch( std::string appName ) {};
    7468  void dontCatch() {};
    7569  void registerCallback( SignalCallback cb, void * someData ) {};
Note: See TracChangeset for help on using the changeset viewer.