[ImageJ-devel] Deadlock: DefaultStatusService.showStatus calls EventService.publish / AbstractColorTool.drawIcon gets active dataset view

Barry DeZonia bdezonia at gmail.com
Mon Sep 30 14:32:37 CDT 2013


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/0ed40c42/attachment-0001.html>


More information about the ImageJ-devel mailing list