[kaffe] patch for unix-jthreads: thread dump on demand

jrandom jrandom at i2p.net
Sun Aug 29 16:18:05 PDT 2004


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi y'all,

Here's a quick patch to let unix-jthreads dump the thread info to
stdout on SIGUSR2 (SIGUSR1 is taken by some deadlock code).  This
just reuses a bunch of existing code to spit out the state of each
thread (e.g. "`Admin Listener:4002' tid 0x98d000c, status
SUSPENDED flags BLOCKEDEXTERNAL blocked: reading from fd 32")

I wanted to get more detailed data in the output - the full stack
trace of where each thread is - but I kept on getting lost (have
I mentioned my C is very rusty lately?)  I refactored a bit of
stackTrace.c to let me pass in a (stackTraceInfo *) directly to
printStackTrace, but I must have been doing something wrong as
I'd either get all of the displayed traces with no frames or it'd
barf on an assert while throwing an exception to tell me I suck.

If anyone has any suggestions for another way to get the stack traces
of the threads in unix-jthreads programatically, I'd love to hear
'em!  Getting a thread dump to tell me what all of my threads are
doing is something I do often in that other VM.

Also in this patch is the unix-jthread fix from before [1] (with
Guilhem's fix [2]) which isn't in CVS yet </nag> :)

hth,
=jr

[1] http://www.kaffe.org/pipermail/kaffe/2004-August/099245.html
[2] http://www.kaffe.org/pipermail/kaffe/2004-August/099246.html

-----BEGIN PGP SIGNATURE-----
Version: PGP 8.1

iQA/AwUBQTJjgxpxS9rYd+OGEQIo7wCfX6Q0t1Jgfn6eKQ3+o+XfnbIzgosAoPII
GYESft6a9OZ8KdN4zK7Ux1bY
=nP6A
-----END PGP SIGNATURE-----
-------------- next part --------------
Index: signal.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/systems/unix-jthreads/signal.c,v
retrieving revision 1.24
diff -u -r1.24 signal.c
--- signal.c	11 Jul 2004 17:44:55 -0000	1.24
+++ signal.c	29 Aug 2004 23:07:13 -0000
@@ -191,6 +191,7 @@
 #endif /* defined(SIGVTALRM) */
 		|| (sig == SIGIO)
 		|| (sig == SIGUSR1)
+		|| (sig == SIGUSR2)
 		|| (sig == SIGCHLD);
 #endif /* !defined(NDEBUG) */
 
-------------- next part --------------
Index: jthread.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/systems/unix-jthreads/jthread.c,v
retrieving revision 1.118
diff -u -r1.118 jthread.c
--- jthread.c	27 Aug 2004 08:41:01 -0000	1.118
+++ jthread.c	29 Aug 2004 23:08:11 -0000
@@ -22,6 +22,8 @@
 /* For NOTIMEOUT */
 #include "jsyscall.h"
 
+/* For Hjava_lang_VMThread */
+#include "thread.h"
 
 /* Flags used for threading I/O calls */
 #define TH_READ                         0
@@ -677,6 +679,28 @@
 }
 
 /*
+ * print info about a java thread (hopefully we'll get this to include more
+ * detail, such as the actual stack traces for each thread)
+ *
+ */
+static void
+dumpJavaThreadLocal(jthread_t thread, UNUSED void *p)
+{
+	Hjava_lang_VMThread *tid = (Hjava_lang_VMThread *)jthread_get_data(thread)->jlThread;
+	dprintf("`%s' ", nameThread(tid));
+	jthread_dumpthreadinfo(thread);
+	dprintf("\n");
+}
+
+static void
+dumpThreadsLocal(void)
+{
+	dprintf("Dumping live threads:\n");
+	jthread_walkLiveThreads(dumpJavaThreadLocal, NULL);
+}
+
+
+/*
  * handle an interrupt.
  * 
  * this function is either invoked from within a signal handler, or as the
@@ -694,6 +718,10 @@
 		ondeadlock();
 		break;
 
+	case SIGUSR2:
+		dumpThreadsLocal();
+		break;
+
 #if defined(SIGVTALRM)
 	case SIGVTALRM:
 		handleVtAlarm(sig, sc);
@@ -1233,6 +1261,7 @@
 	registerAsyncSignalHandler(SIGIO, interrupt);
         registerAsyncSignalHandler(SIGCHLD, interrupt);
         registerAsyncSignalHandler(SIGUSR1, interrupt);
+        registerAsyncSignalHandler(SIGUSR2, interrupt);
 
 	/* 
 	 * If debugging is not enabled, set stdin, stdout, and stderr in 
@@ -2144,10 +2173,39 @@
 		FD_SET(sigPipe[0], &rd);
 #endif
 	}
+
+        /*
+	 * find out if we have any threads waiting (and if so, when the first
+	 * one will expire).  we use this to prevent indefinite waits in the
+	 * poll / select
+	 *
+	 */
+	jlong firstAlarm = -1;
+	if (alarmList != 0) {
+		// sorted
+		firstAlarm = JTHREADQ(alarmList)->time;
+	}
+
+	jlong maxWait = (canSleep ? -1 : 0);
+	if ( (firstAlarm != -1) && (canSleep) ) {
+		jlong curTime = currentTime();
+		if (curTime >= firstAlarm) {
+			maxWait = 0;
+		} else {
+			maxWait = firstAlarm - curTime;
+		}
+		DBG(JTHREADDETAIL, dprintf("handleIO(sleep=%d) maxWait=%d\n", canSleep, maxWait); )
+	}
+
 #if USE_POLL
-	r = poll(pollarray, nfd, canSleep ? -1 : 0);
+	r = poll(pollarray, nfd, maxWait);
 #else
-	r = select(maxFd+1, &rd, &wr, 0, canSleep ? 0 : &zero);
+	if (maxWait <= 0) {
+		r = select(maxFd+1, &rd, &wr, 0, &zero);
+	} else {
+		struct timeval maxWaitVal = { maxWait/1000, (maxWait % 1000) * 1000 };
+		r = select(maxFd+1, &rd, &wr, 0, &maxWaitVal);
+	}
 #endif
 	/* Reset wouldlosewakeup here */
 	wouldlosewakeup = 0; 


More information about the kaffe mailing list