Possible racing condition when using a modal dialog and a TreeView in virtual mode and with VirtualTreeModel

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Possible racing condition when using a modal dialog and a TreeView in virtual mode and with VirtualTreeModel

Maxim Fridental
We have a racing condition in our program we can reproduce. Evaluate the
following:

"open a tree view"
treeModel := VirtualTreeModel new.
treeModel getParentBlock: [:x | 0];
                   getChildrenBlock: [:x | Processor sleep: 100. "Allow the
ex-Main process to run"
                                               #(1 2 3)].
treePresenter := TreePresenter showOn: treeModel.
treePresenter view updateMode: #dynamic. "Change this to #static if you
don't want GPF"
"simulate a 'modal dialog' opening"
Processor forkMainIfMain.
"Now quickly change tree model twice"
treeModel roots: #(0).
Processor sleep: 50.  "Allow the Main process to start painting with
callbacks"
treeModel roots: #().

You should see an "Invalid access to memory location". This occurs when you
have two Smalltalk processes, that let each other to run AND changing the
same TreeView. We have the following understanding of this case:
1) The ex-Main process (the process after forkMainIfMain) changes the tree
model roots. A new tree view item is synchronously added to the tree
control.
2) The ex-Main process waits and thereby allows the Main process to run.
3) The Main process receives a TVN_GETDISPINFO callback from the tree
control and call among other things the getChildrenBlock, where it must
wait.
4) As the Main process waits is the ex-Main process resumed. It changes the
tree model roots again, so the TreeView sends the message TVM_DELETEITEM
with TVI_ROOT. After that the ex-Main dies.
5) It's turn of the Main process now. It leaves the getChildrenBlock and
finishes the callback... for an already deleted item! Tree view control
crashes.

To workaround the problem we've set the updateMode of the tree view to
#static. What is the right solution of this problem? It's not so easy to
remove all delays and semaphores in the both processes, because they are
part of our business logic.


Best Regards,
Maxim Fridental


Reply | Threaded
Open this post in threaded view
|

Re: Possible racing condition when using a modal dialog and a TreeView in virtual mode and with VirtualTreeModel

Blair McGlashan-2
"Maxim Fridental" <[hidden email]> wrote in message
news:bpqbal$1rmi6d$[hidden email]...
> We have a racing condition in our program we can reproduce. Evaluate the
> following:
>
> "open a tree view"
>[...code snipped...]
>
> You should see an "Invalid access to memory location". This occurs when
you

> have two Smalltalk processes, that let each other to run AND changing the
> same TreeView. We have the following understanding of this case:
> 1) The ex-Main process (the process after forkMainIfMain) changes the tree
> model roots. A new tree view item is synchronously added to the tree
> control.
> 2) The ex-Main process waits and thereby allows the Main process to run.
> 3) The Main process receives a TVN_GETDISPINFO callback from the tree
> control and call among other things the getChildrenBlock, where it must
> wait.
> 4) As the Main process waits is the ex-Main process resumed. It changes
the
> tree model roots again, so the TreeView sends the message TVM_DELETEITEM
> with TVI_ROOT. After that the ex-Main dies.
> 5) It's turn of the Main process now. It leaves the getChildrenBlock and
> finishes the callback... for an already deleted item! Tree view control
> crashes.

I would say your analysis is correct. The TreeView does not like its
contents being changed while in the middle of a callback notification. The
method comment of IconicListAbstract>>onLabelOf:editedTo: describes a
situation where this has previously arisen (it also demonstrates our usual
solution, more below).

>
> To workaround the problem we've set the updateMode of the tree view to
> #static. What is the right solution of this problem? It's not so easy to
> remove all delays and semaphores in the both processes, because they are
> part of our business logic.

Using #static is an option, but this is best reserved for cases where the
internal model is unstable and one doesn't want the TreeView attempting to
repaint the tree while the model is restructuring. It has the dowside of
losing the ability to refresh the tree content merely by repainting it.

Really what you need to do is to avoid updating the tree from anywhere but
the main UI process. Dialogs can make this tricky. For further background on
this search the newsgroup archived for the thread "User Interface single or
multi threaded", initiated by Bill Dargel on 21 Feb 2003. My reply (which
does not seem to be on Google Groups) explains the way dialogs are
implemented and provides a design rationale.

The easiest way to ensure that updates are done from the main UI process is
to 'post' a block to the input queue to perform the actions taken after the
dialog is closed. In this particular case you only need to post the final
setting of the tree roots to prevent the GPF, so to get it working:

    ....
    [treeModel roots: #()] postToInputQueue

However one should really post everything after the #forkMainIfMain.

Another less intrusive (into the code anyway) solution is to modify
DialogView to use #runModalInProcessLoop instead of #runModalLoop. This
will, however, mean that you can no longer open more than one modal dialog
at a time unless the dialogs are nested. This isn't an issue for many
applications which have a single main window, though it is an unpleasant
limitation in the multi-windowed Dolphin IDE. This approach could be
employed quite neatly by creating a task modal (rather than view modal)
subclass of DialogView that uses #runModalInProcessLoop, and then using that
dialog view as the shell for the application's dialog view resources.

Hope this helps

Blair


Reply | Threaded
Open this post in threaded view
|

Re: Possible racing condition when using a modal dialog and a TreeView in virtual mode and with VirtualTreeModel

Carsten Haerle
Could you please repost the thread (it is not on the google groups indeed).

"Blair McGlashan" <blair@no spam object-arts.com> schrieb im Newsbeitrag
news:3fc36185$[hidden email]...

> "Maxim Fridental" <[hidden email]> wrote in message
> news:bpqbal$1rmi6d$[hidden email]...
> > We have a racing condition in our program we can reproduce. Evaluate the
> > following:
> >
> > "open a tree view"
> >[...code snipped...]
> >
> > You should see an "Invalid access to memory location". This occurs when
> you
> > have two Smalltalk processes, that let each other to run AND changing
the
> > same TreeView. We have the following understanding of this case:
> > 1) The ex-Main process (the process after forkMainIfMain) changes the
tree

> > model roots. A new tree view item is synchronously added to the tree
> > control.
> > 2) The ex-Main process waits and thereby allows the Main process to run.
> > 3) The Main process receives a TVN_GETDISPINFO callback from the tree
> > control and call among other things the getChildrenBlock, where it must
> > wait.
> > 4) As the Main process waits is the ex-Main process resumed. It changes
> the
> > tree model roots again, so the TreeView sends the message TVM_DELETEITEM
> > with TVI_ROOT. After that the ex-Main dies.
> > 5) It's turn of the Main process now. It leaves the getChildrenBlock and
> > finishes the callback... for an already deleted item! Tree view control
> > crashes.
>
> I would say your analysis is correct. The TreeView does not like its
> contents being changed while in the middle of a callback notification. The
> method comment of IconicListAbstract>>onLabelOf:editedTo: describes a
> situation where this has previously arisen (it also demonstrates our usual
> solution, more below).
>
> >
> > To workaround the problem we've set the updateMode of the tree view to
> > #static. What is the right solution of this problem? It's not so easy to
> > remove all delays and semaphores in the both processes, because they are
> > part of our business logic.
>
> Using #static is an option, but this is best reserved for cases where the
> internal model is unstable and one doesn't want the TreeView attempting to
> repaint the tree while the model is restructuring. It has the dowside of
> losing the ability to refresh the tree content merely by repainting it.
>
> Really what you need to do is to avoid updating the tree from anywhere but
> the main UI process. Dialogs can make this tricky. For further background
on
> this search the newsgroup archived for the thread "User Interface single
or
> multi threaded", initiated by Bill Dargel on 21 Feb 2003. My reply (which
> does not seem to be on Google Groups) explains the way dialogs are
> implemented and provides a design rationale.
>
> The easiest way to ensure that updates are done from the main UI process
is
> to 'post' a block to the input queue to perform the actions taken after
the

> dialog is closed. In this particular case you only need to post the final
> setting of the tree roots to prevent the GPF, so to get it working:
>
>     ....
>     [treeModel roots: #()] postToInputQueue
>
> However one should really post everything after the #forkMainIfMain.
>
> Another less intrusive (into the code anyway) solution is to modify
> DialogView to use #runModalInProcessLoop instead of #runModalLoop. This
> will, however, mean that you can no longer open more than one modal dialog
> at a time unless the dialogs are nested. This isn't an issue for many
> applications which have a single main window, though it is an unpleasant
> limitation in the multi-windowed Dolphin IDE. This approach could be
> employed quite neatly by creating a task modal (rather than view modal)
> subclass of DialogView that uses #runModalInProcessLoop, and then using
that
> dialog view as the shell for the application's dialog view resources.
>
> Hope this helps
>
> Blair
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Possible racing condition when using a modal dialog and a TreeView in virtual mode and with VirtualTreeModel

Ian Bartholomew-18
Carsten,

> Could you please repost the thread (it is not on the google groups
> indeed).

If you go to http://www.idb.me.uk/news.html you can find the posts you
want in the archive.  You will need the Feb 2003 file (there are only
two posts in the thread).

--
Ian


Reply | Threaded
Open this post in threaded view
|

Re: Possible racing condition when using a modal dialog and a TreeView in virtual mode and with VirtualTreeModel

Bill Schwab-2
In reply to this post by Carsten Haerle
Blair,

> > Another less intrusive (into the code anyway) solution is to modify
> > DialogView to use #runModalInProcessLoop instead of #runModalLoop. This
> > will, however, mean that you can no longer open more than one modal
dialog
> > at a time unless the dialogs are nested. This isn't an issue for many
> > applications which have a single main window, though it is an unpleasant
> > limitation in the multi-windowed Dolphin IDE. This approach could be
> > employed quite neatly by creating a task modal (rather than view modal)
> > subclass of DialogView that uses #runModalInProcessLoop, and then using
> that
> > dialog view as the shell for the application's dialog view resources.

Is that a decision that could be factored into a policy that can be set in a
reasonable way?  The first thing that comes to mind is to default to
allowing independent modal dialogs, and let the session manager change the
policy if it wants.  Those having problems in the IDE would probably want
additional control, but thanks to Smalltalk, they'd have it.

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Possible racing condition when using a modal dialog and a TreeView in virtual mode and with VirtualTreeModel

Blair McGlashan
Bill

You wrote in message news:bqisbf$22k1f1$[hidden email]...
>
> > > Another less intrusive (into the code anyway) solution is to modify
> > > DialogView to use #runModalInProcessLoop instead of #runModalLoop.
This
> > > will, however, mean that you can no longer open more than one modal
> dialog
> > > at a time unless the dialogs are nested. This isn't an issue for many
> > > applications which have a single main window, though it is an
unpleasant
> > > limitation in the multi-windowed Dolphin IDE. This approach could be
> > > employed quite neatly by creating a task modal (rather than view
modal)
> > > subclass of DialogView that uses #runModalInProcessLoop, and then
using
> > that
> > > dialog view as the shell for the application's dialog view resources.
>
> Is that a decision that could be factored into a policy that can be set in
a
> reasonable way?  The first thing that comes to mind is to default to
> allowing independent modal dialogs, and let the session manager change the
> policy if it wants.  Those having problems in the IDE would probably want
> additional control, but thanks to Smalltalk, they'd have it.

I suppose that could be done, but that would introduce a difference in
behaviour between development and runtime environments. I think it might be
better to allow this to be specified on a per dialog basic, probably by
having a flag that can be set in much the same way that one can specify task
modal message boxes.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: Possible racing condition when using a modal dialog and a TreeView in virtual mode and with VirtualTreeModel

Bill Schwab-2
Blair,

> I suppose that could be done, but that would introduce a difference in
> behaviour between development and runtime environments.

That's not necessarily all bad, since one will almost certainly want to
switch to a different window and do something in the IDE, where many
single-shell apps will not offer that option, and might benefit from the
stricter/safer approach to modality.  However...

> I think it might be
> better to allow this to be specified on a per dialog basic, probably by
> having a flag that can be set in much the same way that one can specify
task
> modal message boxes.

That sounds great!

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]