Thread: [Sablevm-developer] Thread.interrupted() - mess? (screenshot!)
Brought to you by:
egagnon
From: Grzegorz B. P. <ga...@de...> - 2004-03-07 02:50:24
|
Hi all, it'll be a longer email... I have a working implementation of interrupted(). I must say it's not the best documented part of Java platform, so between the moment I started a few days ago (and in fact coded it) and now, I had some discussions (notably with Tom Tromey and Mark Wielaard), I also looked at how JCVM and Kaffe handle these things... And I'll be rewriting it surely. The question is: how should it work? Doubts: * to set a flag in interrupt handler or not Reasonably simplistic implementation would just check for EINTR, set the flag in env->thread and throw the exception. But EINTR may also happen if nobody called interrupt() and AFAIK in many such cases we should get back to the syscal which was interrupted. On the contrary, what JCVM does seems a bit dangerous, like getting exclusive VM lock in signal handler to set flags... Apparently it can be done even differently - Tom Tromey told me (I haven't looked at the code) GCJ signal handler for interrupt() does nothing. So, my conclusion was that best I can do is set env->thread.interrupted = JNI_TRUE; env->thread.interrupted_thrown = JNI_FALSE; in signal handler, w/o any atomicity. I see no reason as we won't get two same signals at the same time and even if - all they would do would be to also set the same flags. These flags aren't changed by any other thread and _the_ thread is stopped while we execute signal handler for it. * when a thread is considered to be interrupted? Is it: when some other thread sends interrupt() or when the thread actually notices that and throwns the exception? I think rather the latter, and so should isInterrupted() act (checking both flags). * what does it mean that a thread notices it's been interrupt()ed? Even if I have a flag set from interrupt handler and I also check EINTR, it still may happen, that loooong ago some other thrad called interrupt() which set the flag but didn't interrupt any syscall, then after some undefined time I get into completly another method in a program which happened to call ex. wait() and wait gets EINTR (ex. pthread_cond_wait() can spuriously wake up! btw. JCVM implementation is superior here). So we match the EINTR with set-up-long-ago interrupted flag and we throw InterruptedExcpetion instead of getting back to *_cond_wait()! Is that expected behavior? if not - where should I reset interrupted flag? on the entry to the wait() function? * do we need to take into account thread status? Ex. not send the signal if thread is in SVM_THREAD_STATUS_NOT_RUNNING_JAVA_RESUMING_DISALLOWED? (if I send the signal the syscall will be interrupted already). * I wonder how much atomicity we need here. But FWICS it all looks like "one thread is trying to kick another one but it's not guaranteed to work" kind of java feature, so I am not sure how much should I worry about these things. What are the borders of what's acceptable? Not sure. Grzegorz B. Prokopski PS: Other notes: * I'll probably send a note when the code for Thread.interrupt() is put into the SVN (my private branch) for review. * both JCVM and SableVM seem to share the same bug in wait() --- sablevm-1.1.0.orig/src/libsablevm/java_lang_VMObject.c +++ sablevm-1.1.0/src/libsablevm/java_lang_VMObject.c @@ -259,7 +260,8 @@ timeout.tv_nsec = now.tv_usec * 1000; timeout.tv_sec = timeout.tv_sec + (ms / 1000); - timeout.tv_nsec = timeout.tv_nsec + (ms % 1000) + ns; + timeout.tv_nsec = + timeout.tv_nsec + (ms % 1000) * 1000 * 1000 + ns; Which usually makes quite big difference if one wants to wait, say 500ms ;-) (which was previously turned into 500ns) * See http://gadek.debian.net/SableVM-SymbolTest-Working.png ! which is one of the Sun's standard AWT tests. This _didn't_ really work previously, the symbols weren't drawn. Now it works just like on Sun's JVM (minus classpath AWT glitches like lack of text cursor in this edit window where "00" is visible). No hacks used. Unfortunatelly debbuggtk still doesn't work fully when it comes to interrupt()ing another thread. I suspect that it might be Classpath problem with InterruptedException routing. -- Grzegorz B. Prokopski <ga...@de...> Debian GNU/Linux http://www.debian.org SableVM - LGPLed JVM http://www.sablevm.org Why SableVM ?!? http://devel.sablevm.org/wiki/WhySableVM |
From: Grzegorz B. P. <ga...@de...> - 2004-03-07 06:47:25
|
Hi again, sometimes it's good to put things in writing. I think I should have it solved now. This is how it's supposed to work: I have two flags env->thread.interrupted - the same meaning as Thread.interrupted() env->thread.interrupted_signalled both initially JNI_FALSE interrupt handler simply sets interrupted_signalled = JNI_TRUE; before each C function that can return EINTR which I want to possibly turn into InterruptedException I set interrupted_signalled to JNI_FALSE; If I get EINTR and interrupted_signalled changed state to JNI_TRUE I set interrupted to JNI_TRUE and throw InterrupedException Thread.interrupted() returns interrupted flag and sets it to JNI_FALSE Thread.isInterrupted() returns interrupted flag No locking and atomicity anywhere and so far I can't see any reason for it. ATM I think it pretty much should solve all of the problems I outlined in my other mail, though I might be wrong, as the other implementations I saw were much more complicated. My current version of changes is available using command: svn diff -r 1700:HEAD svn://svn.sablevm.org/developers/gadek/sandbox/svn-interrupt (this branch also contains a cople of other fixes but not many) Cheers, Grzegorz B. Prokopski -- Grzegorz B. Prokopski <ga...@de...> Debian GNU/Linux http://www.debian.org SableVM - LGPLed JVM http://www.sablevm.org Why SableVM ?!? http://devel.sablevm.org/wiki/WhySableVM |
From: Grzegorz B. P. <ga...@de...> - 2004-03-09 05:55:59
Attachments:
InterruptTest.java
|
Hi again, Today I discussed the implementation with Etienne, and corrected it a bit. But I was terribly surprised when later it completly didn't work. What's more interesting - the code that worked yesterday - now also doesn't work! (test case java class attached) What has changed is that apparently sending SIGUSR1 to a thread blocked in pthread_cond_timedwait does NOT wake it up (anymore?)! Manual page still says this: The pthread_cond_timedwait function returns the following error codes on error: ETIMEDOUT - the condition variable was not signaled until the timeout specified by |abstime| EINTR - pthread_cond_timedwait was interrupted by a signal So I thought there's some new bug after upgrades I did yesterday... but http://www.opengroup.org/onlinepubs/007904975/functions/pthread_cond_wait.html says: "If a signal is delivered to a thread waiting for a condition variable, upon return from the signal handler the thread resumes waiting for the condition variable as if it was not interrupted, or it shall return zero due to spurious wakeup." and later: "These functions shall not return an error code of [EINTR]." So it looks like for each thread we would need to store information where it currently is waiting (if anywhere) and if needed - signal such thread to unblock (or rather all of the waiting threads). These two look promising, though I think it's more logical to use ..._broadcast(). int pthread_cond_broadcast(pthread_cond_t *cond); int pthread_cond_signal(pthread_cond_t *cond); I'll try to implement that tomorrow but if anybody has better idea, or some advices, I'll be glad to hear. eh, TANSTAAFL... Cheers, Grzegorz B. Prokopski -- Grzegorz B. Prokopski <ga...@de...> Debian GNU/Linux http://www.debian.org SableVM - LGPLed JVM http://www.sablevm.org Why SableVM ?!? http://devel.sablevm.org/wiki/WhySableVM |
From: Grzegorz B. P. <ga...@de...> - 2004-03-10 08:29:09
|
Hi again, I think I finally did it, w/o any compromises on specs conformance. It should work fully according to Java specs about interrupt() and OpenGroup specs about pthread_cond_* usage and features. Though it's unfortunatelly much more complicated (I guess I finally found out why the other implementations weren't that small and simple as mine first ;-) Anyway, the changes are in my sandbox, see: svn diff -r 1700:HEAD svn://svn.sablevm.org/developers/gadek/sandbox/svn-interrupt I want to sleep it over, but if till the evening I don't find anything bad in this implementation and don't get any improvement suggestions, I am putting that into staging. Cheers, GBP -- Grzegorz B. Prokopski <ga...@de...> Debian GNU/Linux http://www.debian.org SableVM - LGPLed JVM http://www.sablevm.org Why SableVM ?!? http://devel.sablevm.org/wiki/WhySableVM |
From: Chris P. <chr...@ma...> - 2004-03-10 16:49:24
|
Grzegorz B. Prokopski wrote: >Hi again, > >I think I finally did it, w/o any compromises on specs conformance. >It should work fully according to Java specs about interrupt() and >OpenGroup specs about pthread_cond_* usage and features. Though it's >unfortunatelly much more complicated (I guess I finally found out why >the other implementations weren't that small and simple as mine first >;-) > >Anyway, the changes are in my sandbox, see: >svn diff -r 1700:HEAD >svn://svn.sablevm.org/developers/gadek/sandbox/svn-interrupt > >I want to sleep it over, but if till the evening I don't find anything >bad in this implementation and don't get any improvement suggestions, >I am putting that into staging. > > Why don't you try some Thread.interrupted() benchmarks and perhaps also some small programs that you write to call it intensively? |