[gccsdk] Threading + Alt-Break = Trashed Computer
bavison at riscosopen.org
Sat Jul 12 16:05:43 PDT 2008
John Tytgat <John.Tytgat at aaug.net> wrote:
> Actually Wimp's Watchdog.s in ROOL's codebase is pretty clear : in
> watchdogcallback you have around line 209 the test whether the current
> task needs to die or not. In case of the former a more or less straight
> OS_Exit is done and that's the case which works as expected.
You're right, I didn't read it properly first time - just naïvely assumed
that the obvious thing to happen was for the exit handler to always be
called. The exit handler is actually only called if it's the current task
that's being killed, as you say. This in itself is a problem for removing
UnixLib's handlers - you'll need to rely on either Service_WimpCloseDown or
Message_TaskCloseDown to detect the removal of the task.
> In the other case, the chosen task is delinked from the Wimp's internals
> and that's it. This means the chosen task's exit handler does not get
> called (and I don't think the environment is left in a sane state
My initial impression of the code was "that must be doing something clever"
but having studied it a bit more, I think it's just plain wrong. If I had
to guess, I'd say it was written by someone who didn't know you can pass a
task handle parameter to Wimp_CloseDown. The task paging appears to be
solely to ensure that the correct task is terminated by Wimp_CloseDown, but
Wimp_CloseDown is written so as to postpone some of the cleanup until the
following call to Wimp_Poll if it's the current task that's being killed. To
compensate for this, they've cut-and-pasted the cleanup code from Wimp_Poll
into the Watchdog, but it has the unfortunate side-effect of screwing up the
environment for the task that was active when the key event went off.
I've tried changing this to use a parameterised call to Wimp_CloseDown and
this fixes the faulty test case I posted yesterday. As this is a worthwhile
fix in its own right, I'll upload it to the ROOL CVS repository shortly.
> I'm wondering why we don't have after the 'pageintask' call a SWI OS_Exit
> call as well.
Having thought about it, I can see why not. OS_Exit will flatten the SVC
stack - and since we're inside a transient callback, the SVC stack may have
quite a lot on it. When the exit handlers bubble out to the Wimp's exit
handler, that will try to exit via Wimp_Poll, which has no way to know it
needs to resume the task that was active when the key event went off, even
if it could do so (which it can't because the SVC stack is trashed).
However, I believe this *could* be fixed if the Wimp had a state flag that
was flipped which affected the behaviour of the Wimp's exit handler. The
Watchdog could then store away a copy of the SVC stack, do a context and
environment switch, set the flag, call OS_Exit, and then when the Wimp's
exit handler is called, it would switch the environment and context back
again, close down the dying task, restore the SVC stack and exit the
Would this be useful enough behaviour to warrant the effort to implement it
though? We've managed without since RISC OS 3.5, but it's potentially a Bad
Thing that we've lacked it, because it can cause all sorts of resource
leaks. (Also, I assume UnixLib's atexit functions are called from its exit
handler - that's certainly the case with the Shared C Library - because
you'd probably want these to be called on an Alt-Break too.)
It could be argued that this would be a retrograde step, because if an
application has a rogue exit handler which refuses to terminate while the
task is not the active task, then you would no longer be able to kill it
after such a change. So it's probably a good idea for an Alt-Break during
the exit handler to revert to the old behaviour by reinstalling the Wimp's
exit handler and trying again.
More information about the gcc