mozart/mozart2

Mozart should warn when suspending on an "unreachable" variable.

Closed this issue · 11 comments

The following code has driven me nuts :

functor
import
   Application

define
   local A in
      {Wait A}
      {Application.exit 9}
   end
end

When compiled and executed with ozengine test.ozf, the program exits immediately with an exit value of zero.

I would expect a warning when mozart detects that no progress is possible while instructions remain on the stack.
I know it may not be the purest thing to do, but it would be most helpful. Terminating a process by waiting forever on an unbound variable is not an expected design.

sjrd commented

Can't do. There are many cases where this is exactly what you want. For example, if you have an infinite handler thread processing a stream, it will block on the tail. But if no one feeds any events to that stream anymore, it is fine for the process to terminate normally.

Agreed, but it is also fine for the process to continue doing nothing forever.
(Except for performance)

In the case of the infinite handler thread processing a stream, I see no problem emitting a warning/debug message that explains why an infinite process stopped running.

Maybe blocked threads could be added to some 'blocked' list instead of just getting out of the runnable list? So when exiting we could have a message saying X threads were blocked (and other usages such as backtraces). Not sure it's a good idea. Waiting forever does not seem appealing to me at least.

To satisfy my curiosity : How do you tell a blocked thread from a waiting thread ?

sjrd commented

To satisfy my curiosity : How do you tell a blocked thread from a waiting thread ?

Precisely, you can't, because they're the same thing.

Ok, let's drop this.
It will be difficult to implement, an is not really wise either :)

I suppose students will need to be careful to avoid errors at this level as they are not errors, just another valid program. Useless but valid...

@sjrd What about Runnable::isRunnable() or ThreadPool::isScheduled(Runnable* thread) ?

sjrd commented

What about them?

Is a runnable thread a non-blocked thread?
And is a blocked thread always unscheduled?
I thought that was the case when I read that part of the code a few months ago.

sjrd commented

A runnable thread is always non-blocked, and either scheduled or running.
A non-runnable thread is never scheduled, but it can either be waiting on a reachable variable (in which case it can become runnable again if that variable is bound or made needed), or it can be stuck forever and hence garbage collected. The difference between these two states is only a matter of reachability analysis done by the GC. But even the unreachable state can be a valid use of a thread, as I have explained before. So I'm not quite sure what you expect these functions to help with in this matter.

Just a bit of insight about the different concepts, like you just wrote, thanks!