Wow, that's a good analysis of the problem, Hendrik. Thank you.
Would you like to investigate this a bit deeper and come up with a fix
for JDK? We would gladly accept a contribution from you. You can find
more information on how to get started here:
http://openjdk.java.net/contribute/ Also, the patch would need to be
reviewed on the awt-dev@ mailing list.
Otherwise, I could only add those comments to the bug report and move it
to the JDK project in JIRA so that it becomes visible, but I'm afraid we
won't be able to do much on this issue any time soon because we don't
have a test app that we could use to reproduce the crash and then
confirm whether we've fixed anything or not.
--
best regards,
Anthony
On 8/29/2014 4:45 PM, Hendrik Schreiber wrote:
On Aug 28, 2014, at 20:16, Anthony Petrov <anthony.pet...@oracle.com> wrote:
JI-9014527 was closed as Incomplete "Not enough information.", supposedly
because there's not a reproducible test case and instructions to reproduce the issue.
That is correct. I erroneously assumed that people reviewing bug reports would
be interested in crashes, and their crashlogs, even if they do not contain
step-by-step instructions on how to reproduce the issue.
If you come up with a simple test that crashes easily, we can re-open that bug.
I wish I could.
BTW, from the full stack trace in the bug report I can see you're running some
accessibility software on your system because the crash happens during an a11y
callback. This may be a contributing factor to the crash. You will need to test
with and without a11y on, and also perhaps try another assistive technology
(e.g. the built-in VoiceOver vs. a third-party software) to see if this changes
anything.
Digging into the source code it becomes clear that
Java_sun_lwawt_macosx_LWCToolkit_stopAWTRunLoop is only called from
- sun.lwawt.macosx.CToolkitThreadBlockedHandler and
- sun.lwawt.macosx.LWCToolkit
The call from LWCToolkit is coded defensively, i.e. it has a 0-check:
if (mediator != 0) {
stopAWTRunLoop(mediator);
}
Therefore it cannot lead to the failure described in
http://www.beatunes.com/download/stopAWTRunLoop.crash
The call from CToolkitThreadBlockedHandler is NOT coded defensively. To the
contrary, it relies on the implicit contract, that the exit() method is called
at most once after the enter() method is called:
public void exit() {
if (!isOwned()) {
throw new IllegalMonitorStateException();
}
LWCToolkit.stopAWTRunLoop(awtRunLoopMediator);
awtRunLoopMediator = 0;
}
It might be a good idea to simply guard against other classes using
enter()/exit() in unintended ways by rewriting it defensively like this:
public void enter() {
if (!isOwned()) {
throw new IllegalMonitorStateException();
}
if (awtRunLoopMediator != 0) {
throw new IllegalStateException("Call exit() first.");
}
awtRunLoopMediator = LWCToolkit.createAWTRunLoopMediator();
unlock();
LWCToolkit.doAWTRunLoop(awtRunLoopMediator, processEvents);
lock();
}
public void exit() {
if (!isOwned()) {
throw new IllegalMonitorStateException();
}
if (awtRunLoopMediator != 0) {
LWCToolkit.stopAWTRunLoop(awtRunLoopMediator);
awtRunLoopMediator = 0;
}
}
That said, enter() and exit() are only called from one place,
sun.awt.datatransfer.DataTransferer#convertData(...).
My guess is, that for some reason getToolkitThreadBlockedHandler().exit(); is
either called multiple times or LWCToolkit.createAWTRunLoopMediator() in
CToolkitThreadBlockedHandler#enter() returns 0 for whatever reason.
Frankly, I don't quite understand how it can happen that the dataConverter
Runnable in DataTransferer#convertData(...) is executed multiple times, but
clearly it is a problem, as the code tries to guard against it. It does not do
so in a threadsafe way though.
Anyhow.
I would appreciate it, if you considered reviewing both my suggestion for
improving sun.lwawt.macosx.CToolkitThreadBlockedHandler and perhaps the code in
sun.awt.datatransfer.DataTransferer to improve the stability of the Java VM on
OS X.
Thank you.
-hendrik