730-debian_gdb-fix-tracefork-check.patch 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. Status: submitted for comments
  2. 2004-11-12 Daniel Jacobowitz <dan@debian.org>
  3. * linux-nat.c (my_waitpid): New function.
  4. (linux_test_for_tracefork): Make more robust and verbose. Take
  5. an ORIGINAL_PID argument and test for PTRACE_SETOPTIONS first.
  6. (linux_supports_tracefork, linux_supports_tracevforkdone): Take a PID
  7. argument. Update calls to linux_test_for_tracefork.
  8. (linux_enable_event_reporting, child_follow_fork)
  9. (child_insert_fork_catchpoint, child_insert_vfork_catchpoint)
  10. (child_insert_exec_catchpoint): Update calls to
  11. linux_supports_tracefork and linux_supports_tracevforkdone.
  12. Index: gdb-6.3/gdb/linux-nat.c
  13. ===================================================================
  14. --- gdb-6.3.orig/gdb/linux-nat.c 2004-10-08 16:29:47.000000000 -0400
  15. +++ gdb-6.3/gdb/linux-nat.c 2004-11-13 16:41:51.368720845 -0500
  16. @@ -150,18 +150,47 @@ linux_tracefork_child (void)
  17. exit (0);
  18. }
  19. -/* Determine if PTRACE_O_TRACEFORK can be used to follow fork events. We
  20. +/* Wrapper function for waitpid which handles EINTR. */
  21. +
  22. +static int
  23. +my_waitpid (int pid, int *status, int flags)
  24. +{
  25. + int ret;
  26. + do
  27. + {
  28. + ret = waitpid (pid, status, flags);
  29. + }
  30. + while (ret == -1 && errno == EINTR);
  31. +
  32. + return ret;
  33. +}
  34. +
  35. +/* Determine if PTRACE_O_TRACEFORK can be used to follow fork events.
  36. +
  37. + First, we try to enable fork tracing on ORIGINAL_PID. If this fails,
  38. + we know that the feature is not available. This may change the tracing
  39. + options for ORIGINAL_PID, but we'll be setting them shortly anyway.
  40. +
  41. + However, if it succeeds, we don't know for sure that the feature is
  42. + available; old versions of PTRACE_SETOPTIONS ignored unknown options. We
  43. create a child process, attach to it, use PTRACE_SETOPTIONS to enable
  44. - fork tracing, and let it fork. If the process exits, we assume that
  45. - we can't use TRACEFORK; if we get the fork notification, and we can
  46. - extract the new child's PID, then we assume that we can. */
  47. + fork tracing, and let it fork. If the process exits, we assume that we
  48. + can't use TRACEFORK; if we get the fork notification, and we can extract
  49. + the new child's PID, then we assume that we can. */
  50. static void
  51. -linux_test_for_tracefork (void)
  52. +linux_test_for_tracefork (int original_pid)
  53. {
  54. int child_pid, ret, status;
  55. long second_pid;
  56. + linux_supports_tracefork_flag = 0;
  57. + linux_supports_tracevforkdone_flag = 0;
  58. +
  59. + ret = ptrace (PTRACE_SETOPTIONS, original_pid, 0, PTRACE_O_TRACEFORK);
  60. + if (ret != 0)
  61. + return;
  62. +
  63. child_pid = fork ();
  64. if (child_pid == -1)
  65. perror_with_name ("linux_test_for_tracefork: fork");
  66. @@ -169,7 +198,7 @@ linux_test_for_tracefork (void)
  67. if (child_pid == 0)
  68. linux_tracefork_child ();
  69. - ret = waitpid (child_pid, &status, 0);
  70. + ret = my_waitpid (child_pid, &status, 0);
  71. if (ret == -1)
  72. perror_with_name ("linux_test_for_tracefork: waitpid");
  73. else if (ret != child_pid)
  74. @@ -177,13 +206,23 @@ linux_test_for_tracefork (void)
  75. if (! WIFSTOPPED (status))
  76. error ("linux_test_for_tracefork: waitpid: unexpected status %d.", status);
  77. - linux_supports_tracefork_flag = 0;
  78. -
  79. ret = ptrace (PTRACE_SETOPTIONS, child_pid, 0, PTRACE_O_TRACEFORK);
  80. if (ret != 0)
  81. {
  82. - ptrace (PTRACE_KILL, child_pid, 0, 0);
  83. - waitpid (child_pid, &status, 0);
  84. + ret = ptrace (PTRACE_KILL, child_pid, 0, 0);
  85. + if (ret != 0)
  86. + {
  87. + warning ("linux_test_for_tracefork: failed to kill child");
  88. + return;
  89. + }
  90. +
  91. + ret = my_waitpid (child_pid, &status, 0);
  92. + if (ret != child_pid)
  93. + warning ("linux_test_for_tracefork: failed to wait for killed child");
  94. + else if (!WIFSIGNALED (status))
  95. + warning ("linux_test_for_tracefork: unexpected wait status 0x%x from "
  96. + "killed child", status);
  97. +
  98. return;
  99. }
  100. @@ -192,8 +231,12 @@ linux_test_for_tracefork (void)
  101. PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORKDONE);
  102. linux_supports_tracevforkdone_flag = (ret == 0);
  103. - ptrace (PTRACE_CONT, child_pid, 0, 0);
  104. - ret = waitpid (child_pid, &status, 0);
  105. + ret = ptrace (PTRACE_CONT, child_pid, 0, 0);
  106. + if (ret != 0)
  107. + warning ("linux_test_for_tracefork: failed to resume child");
  108. +
  109. + ret = my_waitpid (child_pid, &status, 0);
  110. +
  111. if (ret == child_pid && WIFSTOPPED (status)
  112. && status >> 16 == PTRACE_EVENT_FORK)
  113. {
  114. @@ -204,34 +247,38 @@ linux_test_for_tracefork (void)
  115. int second_status;
  116. linux_supports_tracefork_flag = 1;
  117. - waitpid (second_pid, &second_status, 0);
  118. - ptrace (PTRACE_DETACH, second_pid, 0, 0);
  119. + my_waitpid (second_pid, &second_status, 0);
  120. + ret = ptrace (PTRACE_KILL, second_pid, 0, 0);
  121. + if (ret != 0)
  122. + warning ("linux_test_for_tracefork: failed to kill second child");
  123. }
  124. }
  125. + else
  126. + warning ("linux_test_for_tracefork: unexpected result from waitpid "
  127. + "(%d, status 0x%x)", ret, status);
  128. - if (WIFSTOPPED (status))
  129. - {
  130. - ptrace (PTRACE_DETACH, child_pid, 0, 0);
  131. - waitpid (child_pid, &status, 0);
  132. - }
  133. + ret = ptrace (PTRACE_KILL, child_pid, 0, 0);
  134. + if (ret != 0)
  135. + warning ("linux_test_for_tracefork: failed to kill child");
  136. + my_waitpid (child_pid, &status, 0);
  137. }
  138. /* Return non-zero iff we have tracefork functionality available.
  139. This function also sets linux_supports_tracefork_flag. */
  140. static int
  141. -linux_supports_tracefork (void)
  142. +linux_supports_tracefork (int pid)
  143. {
  144. if (linux_supports_tracefork_flag == -1)
  145. - linux_test_for_tracefork ();
  146. + linux_test_for_tracefork (pid);
  147. return linux_supports_tracefork_flag;
  148. }
  149. static int
  150. -linux_supports_tracevforkdone (void)
  151. +linux_supports_tracevforkdone (int pid)
  152. {
  153. if (linux_supports_tracefork_flag == -1)
  154. - linux_test_for_tracefork ();
  155. + linux_test_for_tracefork (pid);
  156. return linux_supports_tracevforkdone_flag;
  157. }
  158. @@ -242,12 +289,12 @@ linux_enable_event_reporting (ptid_t pti
  159. int pid = ptid_get_pid (ptid);
  160. int options;
  161. - if (! linux_supports_tracefork ())
  162. + if (! linux_supports_tracefork (pid))
  163. return;
  164. options = PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACEEXEC
  165. | PTRACE_O_TRACECLONE;
  166. - if (linux_supports_tracevforkdone ())
  167. + if (linux_supports_tracevforkdone (pid))
  168. options |= PTRACE_O_TRACEVFORKDONE;
  169. /* Do not enable PTRACE_O_TRACEEXIT until GDB is more prepared to support
  170. @@ -308,7 +355,8 @@ child_follow_fork (int follow_child)
  171. if (has_vforked)
  172. {
  173. - if (linux_supports_tracevforkdone ())
  174. + gdb_assert (linux_supports_tracefork_flag >= 0);
  175. + if (linux_supports_tracevforkdone (0))
  176. {
  177. int status;
  178. @@ -476,7 +524,7 @@ linux_handle_extended_wait (int pid, int
  179. int
  180. child_insert_fork_catchpoint (int pid)
  181. {
  182. - if (! linux_supports_tracefork ())
  183. + if (! linux_supports_tracefork (pid))
  184. error ("Your system does not support fork catchpoints.");
  185. return 0;
  186. @@ -485,7 +533,7 @@ child_insert_fork_catchpoint (int pid)
  187. int
  188. child_insert_vfork_catchpoint (int pid)
  189. {
  190. - if (!linux_supports_tracefork ())
  191. + if (!linux_supports_tracefork (pid))
  192. error ("Your system does not support vfork catchpoints.");
  193. return 0;
  194. @@ -494,7 +542,7 @@ child_insert_vfork_catchpoint (int pid)
  195. int
  196. child_insert_exec_catchpoint (int pid)
  197. {
  198. - if (!linux_supports_tracefork ())
  199. + if (!linux_supports_tracefork (pid))
  200. error ("Your system does not support exec catchpoints.");
  201. return 0;