[ImageJ-devel] Deadlock: DefaultStatusService.showStatus calls EventService.publish / AbstractColorTool.drawIcon gets active dataset view
Lee Kamentsky
leek at broadinstitute.org
Mon Sep 30 14:34:52 CDT 2013
I submitted a patch to scijava-common with the changes.
https://github.com/scijava/scijava-common/pull/13
On Mon, Sep 30, 2013 at 3:32 PM, Barry DeZonia <bdezonia at gmail.com> wrote:
> A proposed fix would be good Lee. I'd like to test the async status update
> code for responsiveness (i.e. when opening a large image let's say). Let me
> know when your fix is in place. Thanks.
>
>
> On Fri, Sep 27, 2013 at 6:54 AM, Lee Kamentsky <leek at broadinstitute.org>wrote:
>
>> Thanks Barry, the email was a little rushed - finished it while going out
>> the door. What do you think about sending the status messages
>> asynchronously? It looks to me like the AWT event processing will display
>> them in the order received, so that makes sure that a "Finished" message
>> will be seen after a "% complete" message. Status reporting is such a
>> common thing - it'd be a shame for all the worker threads to stall because
>> a user was using ImageJ to watch a movie of a cat falling off a TV while
>> their batch job was running.
>>
>> I think I'll submit a patch to DefaultStatusService for asynch reporting
>> and maybe Curtis or you could look it over and accept it. If you reject, NP.
>>
>> --Lee
>>
>>
>> On Thu, Sep 26, 2013 at 7:53 PM, Barry DeZonia <bdezonia at gmail.com>wrote:
>>
>>> Hi Lee,
>>>
>>> I added the synchronized keyword yesterday to fix a bug. We can undo
>>> that change. I can work around the problem in another fashion if necessary.
>>>
>>>
>>> On Thu, Sep 26, 2013 at 3:57 PM, Lee Kamentsky <leek at broadinstitute.org>wrote:
>>>
>>>> Hi all, I'm getting a deadly embrace that happens when the AWT event
>>>> queue thread tries to get a lock within DefaultDatasetView.getColor and
>>>> when DefaultStatusService.showStatus on a worker thread tries to publish a
>>>> synchronous request for status display after taking the
>>>> DefaultDatasetView's lock in DefaultDatasetView.rebuild. It happens
>>>> periodically, but it's timing-dependent, so not so reproducible.
>>>>
>>>> The bug is somewhat debatable. Possible candidates: It's a little
>>>> drastic for DefaultDatasetView.getColor to synchronize on the view itself.
>>>> Maybe some proxy for the color system could have a synchronizing object.
>>>> The other candidate is DefaultEventService.showStatus which could use
>>>> EventService.publishLater - I don't think there's much need for status
>>>> publishers to wait around for the status to show on the screen.
>>>>
>>>> The two stack traces:
>>>> Thread [AWT-EventQueue-0] (Suspended)
>>>> DefaultDatasetView.getColor(ChannelCollection) line: 261 Synchronized
>>>> method on DefaultDatasetView
>>>> FgColorTool(AbstractColorTool).drawIcon() line: 175
>>>> FgColorTool(AbstractColorTool).onEvent(DisplayActivatedEvent) line: 184
>>>> NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not
>>>> available [native method]
>>>> NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
>>>> DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
>>>> Method.invoke(Object, Object...) line: 597
>>>> DefaultEventService$ProxySubscriber<E>.onEvent(E) line: 282
>>>> DefaultEventService$ProxySubscriber<E>.onEvent(Object) line: 1
>>>> DefaultEventBus(ThreadSafeEventService).publish(Object, String,
>>>> Object, List, List, StackTraceElement[]) line: 971
>>>> DefaultEventBus.access$1(DefaultEventBus, Object, String, Object,
>>>> List, List, StackTraceElement[]) line: 1
>>>> DefaultEventBus$1.run() line: 201
>>>> DefaultThreadService.invoke(Runnable) line: 91
>>>> DefaultEventBus.publishNow(Object, String, Object, List, List,
>>>> StackTraceElement[]) line: 195
>>>> DefaultEventBus.publishNow(Object) line: 86
>>>> DefaultEventService.publish(E) line: 95
>>>> DefaultDisplayService.setActiveDisplay(Display<?>) line: 129
>>>> DefaultDisplayService.onEvent(WinActivatedEvent) line: 247
>>>> NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not
>>>> available [native method]
>>>> NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
>>>> DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
>>>> Method.invoke(Object, Object...) line: 597
>>>> DefaultEventService$ProxySubscriber<E>.onEvent(E) line: 282
>>>> DefaultEventService$ProxySubscriber<E>.onEvent(Object) line: 1
>>>> DefaultEventBus(ThreadSafeEventService).publish(Object, String,
>>>> Object, List, List, StackTraceElement[]) line: 971
>>>> DefaultEventBus.access$1(DefaultEventBus, Object, String, Object,
>>>> List, List, StackTraceElement[]) line: 1
>>>> DefaultEventBus$1.run() line: 201
>>>> DefaultThreadService.invoke(Runnable) line: 91
>>>> DefaultEventBus.publishNow(Object, String, Object, List, List,
>>>> StackTraceElement[]) line: 195
>>>> DefaultEventBus.publishNow(Object) line: 86
>>>> DefaultEventService.publish(E) line: 95
>>>> AWTWindowEventDispatcher.windowActivated(WindowEvent) line: 94
>>>> SwingDisplayWindow(Window).processWindowEvent(WindowEvent) line: 1877
>>>> SwingDisplayWindow(JFrame).processWindowEvent(WindowEvent) line: 274
>>>> SwingDisplayWindow(Window).processEvent(AWTEvent) line: 1823
>>>> SwingDisplayWindow(Component).dispatchEventImpl(AWTEvent) line: 4630
>>>> SwingDisplayWindow(Container).dispatchEventImpl(AWTEvent) line: 2099
>>>> SwingDisplayWindow(Window).dispatchEventImpl(AWTEvent) line: 2478
>>>> SwingDisplayWindow(Component).dispatchEvent(AWTEvent) line: 4460
>>>> DefaultKeyboardFocusManager(KeyboardFocusManager).redispatchEvent(Component,
>>>> AWTEvent) line: 1850
>>>> DefaultKeyboardFocusManager.typeAheadAssertions(Component, AWTEvent)
>>>> line: 910
>>>> DefaultKeyboardFocusManager.dispatchEvent(AWTEvent) line: 409
>>>> SwingDisplayWindow(Component).dispatchEventImpl(AWTEvent) line: 4502
>>>> SwingDisplayWindow(Container).dispatchEventImpl(AWTEvent) line: 2099
>>>> SwingDisplayWindow(Window).dispatchEventImpl(AWTEvent) line: 2478
>>>> SwingDisplayWindow(Component).dispatchEvent(AWTEvent) line: 4460
>>>> EventQueue.dispatchEvent(AWTEvent) line: 599
>>>> DefaultKeyboardFocusManager$DefaultKeyboardFocusManagerSentEvent(SentEvent).dispatch()
>>>> line: 55
>>>> DefaultKeyboardFocusManager$DefaultKeyboardFocusManagerSentEvent.dispatch()
>>>> line: 183
>>>> DefaultKeyboardFocusManager.sendMessage(Component, AWTEvent) line: 210
>>>> DefaultKeyboardFocusManager.dispatchEvent(AWTEvent) line: 286
>>>> SwingDisplayWindow(Component).dispatchEventImpl(AWTEvent) line: 4502
>>>> SwingDisplayWindow(Container).dispatchEventImpl(AWTEvent) line: 2099
>>>> SwingDisplayWindow(Window).dispatchEventImpl(AWTEvent) line: 2478
>>>> SwingDisplayWindow(Component).dispatchEvent(AWTEvent) line: 4460
>>>> EventQueue.dispatchEvent(AWTEvent) line: 599
>>>> SequencedEvent.dispatch() line: 101
>>>> EventQueue.dispatchEvent(AWTEvent) line: 597
>>>> EventDispatchThread.pumpOneEventForFilters(int) line: 269
>>>> EventDispatchThread.pumpEventsForFilter(int, Conditional,
>>>> EventFilter) line: 184
>>>> EventDispatchThread.pumpEventsForHierarchy(int, Conditional, Component)
>>>> line: 174
>>>> EventDispatchThread.pumpEvents(int, Conditional) line: 169
>>>> EventDispatchThread.pumpEvents(Conditional) line: 161
>>>> EventDispatchThread.run() line: 122
>>>>
>>>> Thread [SciJava-4b2922f6-Thread-27] (Suspended)
>>>> Object.wait(long) line: not available [native method]
>>>> EventQueue$1AWTInvocationLock(Object).wait() line: 485 Waiting for AWT
>>>> event thread to read invocation request.
>>>> EventQueue.invokeAndWait(Runnable) line: 993
>>>> DefaultThreadService.invoke(Runnable) line: 95
>>>> DefaultEventBus.publishNow(Object, String, Object, List, List,
>>>> StackTraceElement[]) line: 195
>>>> DefaultEventBus.publishNow(Object) line: 86
>>>> DefaultEventService.publish(E) line: 95
>>>> DefaultStatusService.showStatus(int, int, String) line: 77
>>>> DefaultMinMaxMethod<T>.report() line: 296
>>>> DefaultMinMaxMethod<T>.process() line: 155
>>>> DefaultAutoscaleMethod<T>.getRange(IterableInterval<T>) line: 70
>>>> DefaultAutoscaleService.getDefaultIntervalRange(IterableInterval<RealType<?>>)
>>>> line: 97
>>>> DefaultAutoscaleService.getDefaultRandomAccessRange(RandomAccessibleInterval<RealType<?>>)
>>>> line: 105
>>>> DefaultDatasetView.autoscale(int) line: 176
>>>> DefaultDatasetView.initializeView(boolean) line: 499
>>>> DefaultDatasetView.rebuild() line: 383 Takes the DefaultDatasetView
>>>> lock.
>>>> DefaultImageDisplay.rebuild() line: 140
>>>> DefaultImageDisplay.display(Object) line: 273
>>>> DefaultOverlayService.addOverlays(ImageDisplay, List<Overlay>) line: 148
>>>> TurboRegRegister.run() line: 144
>>>> CommandModule.run() line: 196
>>>> ModuleRunner.run() line: 168
>>>> ModuleRunner.call() line: 129
>>>> ModuleRunner.call() line: 1
>>>> FutureTask$Sync.innerRun() line: 303
>>>> FutureTask<V>.run() line: 138
>>>> ThreadPoolExecutor$Worker.runTask(Runnable) line: 886
>>>> ThreadPoolExecutor$Worker.run() line: 908
>>>> Thread.run() line: 662
>>>>
>>>>
>>>> _______________________________________________
>>>> ImageJ-devel mailing list
>>>> ImageJ-devel at imagej.net
>>>> http://imagej.net/mailman/listinfo/imagej-devel
>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://imagej.net/pipermail/imagej-devel/attachments/20130930/b193afe5/attachment-0001.html>
More information about the ImageJ-devel
mailing list