109 lines · cpp
1#include <errno.h>2#include <fcntl.h>3#include <signal.h>4#include <stdio.h>5#include <stdlib.h>6#include <string.h>7#include <unistd.h>8 9#include <sys/types.h>10#include <sys/ptrace.h>11#include <sys/stat.h>12#include <sys/wait.h>13 14#if defined(PTRACE_ATTACH)15#define ATTACH_REQUEST PTRACE_ATTACH16#define DETACH_REQUEST PTRACE_DETACH17#elif defined(PT_ATTACH)18#define ATTACH_REQUEST PT_ATTACH19#define DETACH_REQUEST PT_DETACH20#else21#error "Unsupported platform"22#endif23 24bool writePid (const char* file_name, const pid_t pid)25{26 char *tmp_file_name = (char *)malloc(strlen(file_name) + 16);27 strcpy(tmp_file_name, file_name);28 strcat(tmp_file_name, "_tmp");29 int fd = open (tmp_file_name, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);30 if (fd == -1)31 {32 fprintf (stderr, "open(%s) failed: %s\n", tmp_file_name, strerror (errno));33 free(tmp_file_name);34 return false;35 }36 char buffer[64];37 snprintf (buffer, sizeof(buffer), "%ld", (long)pid);38 39 bool res = true;40 if (write (fd, buffer, strlen (buffer)) == -1)41 {42 fprintf (stderr, "write(%s) failed: %s\n", buffer, strerror (errno));43 res = false;44 }45 close (fd);46 47 if (rename (tmp_file_name, file_name) == -1)48 {49 fprintf (stderr, "rename(%s, %s) failed: %s\n", tmp_file_name, file_name, strerror (errno));50 res = false;51 }52 free(tmp_file_name);53 54 return res;55}56 57void signal_handler (int)58{59}60 61int main (int argc, char const *argv[])62{63 if (argc < 2)64 {65 fprintf (stderr, "invalid number of command line arguments\n");66 return 1;67 }68 69 const pid_t pid = fork ();70 if (pid == -1)71 {72 fprintf (stderr, "fork failed: %s\n", strerror (errno));73 return 1;74 }75 76 if (pid > 0)77 {78 // Make pause call to return when a signal is received. Normally this happens when the79 // test runner tries to terminate us.80 signal (SIGHUP, signal_handler);81 signal (SIGTERM, signal_handler);82 if (ptrace (ATTACH_REQUEST, pid, NULL, 0) == -1)83 {84 fprintf (stderr, "ptrace(ATTACH) failed: %s\n", strerror (errno));85 }86 else87 {88 if (writePid (argv[1], pid))89 pause (); // Waiting for the debugger trying attach to the child.90 91 if (ptrace (DETACH_REQUEST, pid, NULL, 0) != 0)92 fprintf (stderr, "ptrace(DETACH) failed: %s\n", strerror (errno));93 }94 95 kill (pid, SIGTERM);96 int status = 0;97 if (waitpid (pid, &status, 0) == -1)98 fprintf (stderr, "waitpid failed: %s\n", strerror (errno));99 }100 else101 {102 // child inferior.103 pause ();104 }105 106 printf ("Exiting now\n");107 return 0;108}109