⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 coredumper_unittest.c

📁 能把所有线程的数据和环境记录到文件,方便调试.
💻 C
📖 第 1 页 / 共 2 页
字号:
          }          /* No more patterns. We have a successful match.                   */          if (!c)            goto found;          templ[l] = c;          templ += l + 1;        }      }    found:      /* Print matched pattern. Enter arg into command stream. Then loop.    */      printf("Found: %s", *ptr);      if (arg && *out_ptr == '@') {        /* We only want to match the very last word; drop leading tokens.    */        int rc;        char *last = strrchr(arg, ' ');        if (last != NULL) arg = last + 1;        /* Enter matched data into the command stream.                       */        rc = fputs(arg, input);        assert(rc > 0);        printf(" (arg = \"%s\")", arg);        arg = 0;        out_ptr++;      }      puts("");    }      assert(*dummy == cmp);    printf("Magic marker matches %d\n", *dummy);  }}/* We can test both the WriteCoreDump() and the GetCoreDump() functions * with the same test cases. We just need to wrap the GetCoreDump() * family of functions with some code that emulates the WriteCoreDump() * functions. */static int MyWriteCompressedCoreDump(const char *file_name, size_t max_length,                            const struct CoredumperCompressor compressors[],                            struct CoredumperCompressor **selected_compressor){  int                         rc = 0;  int                         coreFd;  struct CoredumperCompressor *comp;  if (!max_length)    return 0;  coreFd = GetCompressedCoreDump(compressors, &comp);  if (selected_compressor != NULL)    *selected_compressor = comp;  if (coreFd >= 0) {    int writeFd;    const char *suffix = "";    if (comp != NULL && comp->compressor != NULL && comp->suffix != NULL)      suffix = comp->suffix;    /* scope */ {      char extended_file_name[strlen(file_name) + strlen(suffix) + 1];      strcat(strcpy(extended_file_name, file_name), suffix);      writeFd = open(extended_file_name, O_WRONLY|O_CREAT|O_TRUNC, 0600);    }    if (writeFd >= 0) {      char buffer[16384];      ssize_t len;      while (max_length > 0 &&             ((len = read(coreFd, buffer,                          sizeof(buffer) < max_length                          ? sizeof(buffer) : max_length)) > 0 ||              (len < 0 && errno == EINTR))) {        char *ptr = buffer;        while (len > 0) {          int i;          i = write(writeFd, ptr, len);          if (i <= 0) {            rc = -1;            break;          }          ptr        += i;          len        -= i;          max_length -= i;        }      }      close(writeFd);    } else {      rc = -1;    }    close(coreFd);  } else {    rc = -1;  }  return rc;}static int MyWriteCoreDump(const char *file_name) {  return MyWriteCompressedCoreDump(file_name, SIZE_MAX, NULL, NULL);}static int MyWriteCoreDumpLimited(const char *file_name, size_t max_length) {  return MyWriteCompressedCoreDump(file_name, max_length, NULL, NULL);}/* Do not declare this function static, so that the compiler does not get * tempted to inline it. We want to be able to see some stack traces. */void TestCoreDump() {  static struct CoredumperCompressor my_compressor[] = {  { "/NOSUCHDIR/NOSUCHFILE", 0,    0 },  { 0,                       0,    0 }, /* Will be overwritten by test       */  { 0,                       0,    0 } };  int         loop, in[2], out[2], dummy, cmp, rc;  pid_t       pid;  FILE        *input, *output;  pthread_t   thread;  struct stat statBuf;  struct CoredumperCompressor *compressor;  /* Make stdout unbuffered. We absolutely want to see all output, even   * if the application aborted with an assertion failure.   */  setvbuf(stdout, NULL, _IONBF, 0);  /* It is rather tricky to properly call fork() from within a multi-threaded   * application. To simplify this problem, we fork and exec /bin/bash before   * creating the first thread.   */  puts("Forking /bin/bash process");  rc = pipe(in);  assert(!rc);  rc = pipe(out); assert(!rc);  if ((pid = fork()) == 0) {    int i, openmax;    dup2(in[0],  0);    dup2(out[1], 1);    dup2(out[1], 2);    openmax = sysconf(_SC_OPEN_MAX);    for (i = 3; i < openmax; i++)      close(i);    fcntl(0, F_SETFD, 0);    fcntl(1, F_SETFD, 0);    fcntl(2, F_SETFD, 0);    execl("/bin/bash", "bash", "-ex", NULL);    _exit(1);  }  assert(pid >= 0);  assert(!close(in[0]));  assert(!close(out[1]));  input  = fdopen(in[1], "w");  output = fdopen(out[0], "r");  setvbuf(input, NULL, _IONBF, 0);  setvbuf(output, NULL, _IONBF, 0);  /* Create a random value in one of our auto variables; we will later look   * for this value by inspecting the core file with gdb.   */  srand(time(0));  dummy = random();  cmp   = ~dummy;  /* Start some threads that should show up in our core dump; this is   * complicated by the fact that we do not want our threads to perform any   * system calls. So, they are busy looping and checking a volatile   * state variable, instead.   */  puts("Starting threads");  pthread_create(&thread, 0, Busy, (void *)&state1);  pthread_create(&thread, 0, Busy, (void *)&state2);  while (state1 != RUNNING || state2 != RUNNING) {    usleep(100*1000);  }  for (loop = 0; loop < 2; loop++) {    /* Prepare to create a core dump for the current process                 */    puts("Writing core file to \"core-test\"");    unlink("core-test");      /* Check whether limits work correctly                                   */    rc = (loop?MyWriteCoreDumpLimited:WriteCoreDumpLimited)("core-test", 0);    assert(!rc);    assert(stat("core-test", &statBuf) < 0);    rc = (loop?MyWriteCoreDumpLimited:WriteCoreDumpLimited)("core-test", 256);    assert(!rc);    assert(!stat("core-test", &statBuf));    assert(statBuf.st_size == 256);    assert(!unlink("core-test"));      /* Check wether compression works                                        */    puts("Checking compressed core files");    rc = (loop?MyWriteCompressedCoreDump:WriteCompressedCoreDump)           ("core-test", SIZE_MAX, COREDUMPER_GZIP_COMPRESSED, &compressor);    assert(!rc);    assert(compressor);    assert(strstr(compressor->compressor, "gzip"));    assert(!strcmp(compressor->suffix, ".gz"));    CheckWithReadElf(input, output, "core-test", compressor->suffix,                     compressor->compressor, "-d");    assert(!unlink("core-test.gz"));      /* Check wether fallback to uncompressed core files works                */    puts("Checking fallback to uncompressed core files");    my_compressor[1].compressor = NULL; /* Disable uncompressed files        */    rc = (loop?MyWriteCompressedCoreDump:WriteCompressedCoreDump)           ("core-test", SIZE_MAX, my_compressor, &compressor);    assert(rc);    assert(!compressor->compressor);    my_compressor[1].compressor = ""; /* Enable uncompressed files           */    rc = (loop?MyWriteCompressedCoreDump:WriteCompressedCoreDump)           ("core-test", SIZE_MAX, my_compressor, &compressor);    assert(!rc);    assert(compressor->compressor);    assert(!*compressor->compressor);    CheckWithReadElf(input, output, "core-test", "", "cat", "");    assert(!unlink("core-test"));      /* Create a full-size core file                                          */    puts("Checking uncompressed core files");    rc = (loop?MyWriteCoreDump:WriteCoreDump)("core-test");    assert(!rc);    CheckWithReadElf(input, output, "core-test", "", "cat", "");    CheckWithGDB(input, output, "core-test", &dummy, cmp);    /* Get rid of our temporary test file                                    */    unlink("core-test");  }  /* Stop our threads                                                        */  puts("Stopping threads");  state1 = DEAD;  state2 = DEAD;  /* Kill bash process                                                       */  kill(SIGTERM, pid);  fclose(input);  fclose(output);  return;}int main(int argc, char *argv[]) {  static int bloat[1024*1024];  int i;  /* This unittest parses the output from "readelf" and "gdb" in order to   * verify that the core files look correct. And unfortunately, some of   * the messages for these programs have been localized, so the unittest   * cannot always find the text that it is looking for.   * Let's just force everything back to English:   */  putenv(strdup("LANGUAGE=C"));  putenv(strdup("LC_ALL=C"));  /* Make our RSS a little bigger, so that we can test codepaths that do not   * trigger for very small core files. Also, make sure that this data is   * not easily compressible nor in a read-only memory segment.   */  for (i = 0; i < sizeof(bloat)/sizeof(int); i++) {    bloat[i] = rand();  }  TestCoreDump();  puts("PASS");  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -