Browse Source

Fix ratrace

There were several issues. When we moved to the new way of generating system calls and formats
a few things change such that rfork was not correctly detected. This is fixed.

ratrace now has a -d switch, mostly used for detecting when new processes are started.

You can now ratrace -c rc, and see what happens. Even better, you can ratrace -c
listen1 -t tcp cpu!*!17010 cpu -R

and find out why cpu doesn't work.

fixed #27

Change-Id: Ib595623d1c9bd20488b929734308a4b98cf69725
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Ronald G. Minnich 8 years ago
parent
commit
7d275db99e
1 changed files with 32 additions and 6 deletions
  1. 32 6
      sys/src/cmd/ratrace.c

+ 32 - 6
sys/src/cmd/ratrace.c

@@ -21,6 +21,7 @@ Channel *out;
 Channel *quit;
 Channel *forkc;
 int nread = 0;
+int debug = 0;
 
 typedef struct Str Str;
 struct Str {
@@ -62,24 +63,34 @@ newstr(void)
 void
 reader(void *v)
 {
-	int cfd, tfd, forking = 0, exiting, pid, newpid;
+	int cfd, tfd, forking = 0, exiting, pid;
+	uintptr_t newpid;
 	char *ctl, *truss;
 	Str *s;
 	static char start[] = "start";
 	static char waitstop[] = "waitstop";
 
 	pid = (int)(uintptr)v;
+	if (debug)
+		fprint(2, "DEBUG: -------------> reader starts with pid %d\n", pid);
 	ctl = smprint("/proc/%d/ctl", pid);
 	if ((cfd = open(ctl, OWRITE)) < 0)
 		die(smprint("%s: %r", ctl));
 	truss = smprint("/proc/%d/syscall", pid);
 	if ((tfd = open(truss, OREAD)) < 0)
 		die(smprint("%s: %r", truss));
-
+	if (debug)
+		fprint(2, "DEBUG: Send %s to pid %d ...", waitstop, pid);
 	/* child was stopped by hang msg earlier */
 	cwrite(cfd, ctl, waitstop, sizeof waitstop - 1);
+	if (debug)
+		fprint(2, "DEBUG: back for %d\n", pid);
 
+	if (debug)
+		fprint(2, "DEBUG: Send %s to pid %d\n", "startsyscall", pid);
 	cwrite(cfd, ctl, "startsyscall", 12);
+	if (debug)
+		fprint(2, "DEBUG: back for %d\n", pid);
 	s = newstr();
 	exiting = 0;
 	while((s->len = pread(tfd, s->buf, Bufsize - 1, 0)) >= 0){
@@ -94,14 +105,22 @@ reader(void *v)
 		 * There are three tests here and they (I hope) guarantee
 		 * no false positives.
 		 */
+		/* BUG: when we update all the system call generation stuff, we broke rfork tracing.
+		 * The convention is the first letter of the system call in syscallfmt should be upper case.
+		 * This subtlety got lost. FIX ME but it will be tricky.
+		 * The reason to upcase is we need to be careful not to be fooled by random text.
 		if (strstr(s->buf, " Rfork") != nil) {
+		 */
+		if (strstr(s->buf, " rfork") != nil) {
 			char *a[8];
 			char *rf;
 
 			rf = strdup(s->buf);
-         		if (tokenize(rf, a, 8) == 5 &&
-			    strtoul(a[4], 0, 16) & RFPROC)
-				forking = 1;
+			if (tokenize(rf, a, 8) == 4 &&
+				strtoul(a[3], 0, 16) & RFPROC)
+					forking = 1;
+			if (debug)
+				fprint(2, "DEBUG:really forking? %d\n", forking);
 			free(rf);
 		} else if (strstr(s->buf, " Exits") != nil)
 			exiting = 1;
@@ -115,7 +134,11 @@ reader(void *v)
 		}
 
 		/* flush syscall trace buffer */
+		if (debug)
+			fprint(2, "DEBUG: Send %s to pid %d\n", "startsyscall", pid);
 		cwrite(cfd, ctl, "startsyscall", 12);
+		if (debug)
+			fprint(2, "DEBUG: back for %d\n", pid);
 		s = newstr();
 	}
 
@@ -188,7 +211,7 @@ hang(void)
 void
 threadmain(int argc, char **argv)
 {
-	int pid;
+	uintptr_t pid;
 	char *cmd = nil;
 	char **args = nil;
 
@@ -207,6 +230,9 @@ threadmain(int argc, char **argv)
 			cmd = strdup(argv[2]);
 			args = &argv[2];
 			break;
+		case 'd':
+			debug = 1;
+			break;
 		default:
 			usage();
 		}