Make strace somewhat resilient against process disappearing
under its claws. Prime example is sudden SIGKILL.
Fixes RH#472053
diff --git a/strace.c b/strace.c
index 29eb9cb..13459d8 100644
--- a/strace.c
+++ b/strace.c
@@ -1372,10 +1372,8 @@
 		tcp->parent->nclone_waiting--;
 #endif
 
-	if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
-		perror("resume: ptrace(PTRACE_SYSCALL, ...)");
+	if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
 		return -1;
-	}
 
 	if (!qflag)
 		fprintf(stderr, "Process %u resumed\n", tcp->pid);
@@ -1547,21 +1545,14 @@
 				break;
 			}
 			if (WSTOPSIG(status) == SIGSTOP) {
-				if ((error = ptrace(PTRACE_DETACH,
-				    tcp->pid, (char *) 1, sig)) < 0) {
-					if (errno != ESRCH)
-						perror("detach: ptrace(PTRACE_DETACH, ...)");
-					/* I died trying. */
-				}
+				ptrace_restart(PTRACE_DETACH, tcp, sig);
 				break;
 			}
-			if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
-			    WSTOPSIG(status) == SIGTRAP ?
-			    0 : WSTOPSIG(status))) < 0) {
-				if (errno != ESRCH)
-					perror("detach: ptrace(PTRACE_CONT, ...)");
+			error = ptrace_restart(PTRACE_CONT, tcp,
+					WSTOPSIG(status) == SIGTRAP ? 0
+					: WSTOPSIG(status));
+			if (error < 0)
 				break;
-			}
 		}
 #endif /* LINUX */
 
@@ -1570,8 +1561,7 @@
 	if (sig && kill(tcp->pid, sig) < 0)
 		perror("detach: kill");
 	sig = 0;
-	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
-		perror("detach: ptrace(PTRACE_DETACH, ...)");
+	error = ptrace_restart(PTRACE_DETACH, tcp, sig);
 #endif /* SUNOS4 */
 
 #ifndef USE_PROCFS
@@ -2174,17 +2164,16 @@
 			detach(tcp, sig);
 		  	if (leader != NULL && leader != tcp)
 				leader->flags |= TCB_GROUP_EXITING;
-		}
-		else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
-			perror("strace: ptrace(PTRACE_CONT, ...)");
-			cleanup();
-			return -1;
-		}
-		else {
-			if (leader != NULL)
+		} else {
+			if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
+				cleanup();
+				return -1;
+			}
+			if (leader != NULL) {
 				leader->flags |= TCB_GROUP_EXITING;
-			if (leader != NULL && leader != tcp)
-				droptcb(tcp);
+				if (leader != tcp)
+					droptcb(tcp);
+			}
 			/* The leader will report to us as parent now,
 			   and then we'll get to the SIG==-1 case.  */
 			return 0;
@@ -2429,9 +2418,7 @@
 				 * Hope we are back in control now.
 				 */
 				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
-				if (ptrace(PTRACE_SYSCALL,
-						pid, (char *) 1, 0) < 0) {
-					perror("trace: ptrace(PTRACE_SYSCALL, ...)");
+				if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
 					cleanup();
 					return -1;
 				}
@@ -2478,9 +2465,7 @@
 #endif
 				continue;
 			}
-			if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
-				   WSTOPSIG(status)) < 0) {
-				perror("trace: ptrace(PTRACE_SYSCALL, ...)");
+			if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
 				cleanup();
 				return -1;
 			}
@@ -2490,7 +2475,7 @@
 		/* we handled the STATUS, we are permitted to interrupt now. */
 		if (interrupted)
 			return 0;
-		if (trace_syscall(tcp) < 0) {
+		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
 			if (tcp->flags & TCB_ATTACHED)
 				detach(tcp, 0);
 			else {
@@ -2510,8 +2495,7 @@
 #endif
 			if (tcp->flags & TCB_ATTACHED)
 				detach(tcp, 0);
-			else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
-				perror("strace: ptrace(PTRACE_CONT, ...)");
+			else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
 				cleanup();
 				return -1;
 			}
@@ -2523,8 +2507,7 @@
 			continue;
 		}
 	tracing:
-		if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
-			perror("trace: ptrace(PTRACE_SYSCALL, ...)");
+		if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
 			cleanup();
 			return -1;
 		}
@@ -2572,9 +2555,18 @@
 printleader(tcp)
 struct tcb *tcp;
 {
-	if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
-		tcp_last->flags |= TCB_REPRINT;
-		tprintf(" <unfinished ...>\n");
+	if (tcp_last) {
+		if (tcp_last->ptrace_errno) {
+			if (tcp_last->flags & TCB_INSYSCALL) {
+				tprintf(" <unavailable>)");
+				tabto(acolumn);
+			}
+			tprintf("= ? <unavailable>\n");
+			tcp_last->ptrace_errno = 0;
+		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
+			tcp_last->flags |= TCB_REPRINT;
+			tprintf(" <unfinished ...>\n");
+		}
 	}
 	curcol = 0;
 	if ((followfork == 1 || pflag_seen > 1) && outfname)