Permalink
Browse files

Try to stop the target with SIGTSTP before attaching.

This should both cause the target process to redraw / reinitialize the
terminal (since it thinks it's been backgrounded and restarted), and should give
you back the old terminal, since it sees the process now running in the
"background".
  • Loading branch information...
nelhage committed Jan 25, 2011
1 parent 0046dc7 commit 6e5dc87c80c21e3c3cea20c455c485eda7043ea3
Showing with 42 additions and 0 deletions.
  1. +42 −0 attach.c
View
@@ -12,6 +12,8 @@
#include <sys/wait.h>
#include <signal.h>
#include <limits.h>
+#include <time.h>
+#include <sys/time.h>
#include "ptrace.h"
#include "reptyr.h"
@@ -166,13 +168,53 @@ int ignore_hup(struct ptrace_child *child, unsigned long scratch_page) {
return err;
}
+void wait_for_stop(pid_t pid) {
+ struct timeval start, now;
+ struct timespec sleep;
+ char stat_path[PATH_MAX], buf[256], *p;
+ int fd;
+
+ snprintf(stat_path, sizeof stat_path, "/proc/%d/stat", pid);
+ fd = open(stat_path, O_RDONLY);
+ if (!fd) {
+ error("Unable to open %s: %s", stat_path, strerror(errno));
+ return;
+ }
+ gettimeofday(&start, NULL);
+ while (1) {
+ gettimeofday(&now, NULL);
+ if ((now.tv_sec > start.tv_sec && now.tv_usec > start.tv_usec)
+ || (now.tv_sec - start.tv_sec > 1)) {
+ error("Timed out waiting for child stop.");
+ return;
+ }
+ lseek(fd, 0, SEEK_SET);
+ if (read(fd, buf, sizeof buf) <= 0)
+ return;
+ p = strchr(buf, ' ');
+ if (!p)
+ return;
+ p = strchr(p+1, ' ');
+ if (!p)
+ return;
+ if (*(p+1) == 'T')
+ return;
+
+ sleep.tv_sec = 0;
+ sleep.tv_nsec = 10000000;
+ nanosleep(&sleep, NULL);
+ }
+}
+
int attach_child(pid_t pid, const char *pty) {
struct ptrace_child child;
unsigned long scratch_page = -1;
int *child_tty_fds = NULL, n_fds, child_fd;
int i;
int err = 0;
+ kill(pid, SIGTSTP);
+ wait_for_stop(pid);
if (ptrace_attach_child(&child, pid))
return child.error;

0 comments on commit 6e5dc87

Please sign in to comment.