On Wed, Jul 17, 2013 at 10:42 AM, Sandro Magi <[email protected]>wrote:

> I'm confused by what seems to be a topic-shift. We started by discussing
> finalization on task-local resources, but you're here discussing
> finalization that falls entirely outside this scope.
>

Or perhaps I am confused. This, of course, has *never* happened before. :-)
:-)

>From my perspective, the confusion starts with using the word
"finalization" in the context of task exit. There are two things that this
might mean, and I'm not sure which one was intended:

1. Execution of finalizer code within the task before the task vanishes.
This is "finalization" in the sense that the GC world uses the term.

2. Cleanup of underlying OS/runtime/whatever as a consequence of task exit.
In the OS world this is sometimes referred to as "resource cleanup", and it
happens at a layer of the system that is logically below the application.
Indeed, the whole point of this cleanup is that the process is no longer
around, and can't clean up after itself.

Can I suggest that we reserve "finalization" for discussion of in-app
activities (GC style), and use "task cleanup" or "resource cleanup" to
refer to what happens in the next layer down on task exit/destroy?


But I think there was a second, simultaneous confusion, because it wasn't
clear to me whether the "task" we are discussing has some relationship to
an underlying (kernel or runtime) thread or is just a runtime trick in the
language runtime. If it has an underlying (kernel) thread, then it has an
identity that is recognizable by the layer beneath the application, and the
task is thereby able to hold kernel-layer resources directly. Conversely,
if there is no association between a language layer task and a kernel layer
thread, then either a task cannot hold kernel resources or the runtime has
to implement some form of tracking to remember which runtime-owned
resources were associated with that runtime-implemented task. Which can be
done, but it's tricky.

To add to the confusion: if the runtime is tracking the association, then
we can indeed talk about finalization in the first (GC) sense happening for
purposes of task resource cleanup, but in that case it happens in the task
management subsystem of the language runtime. As a matter of
implementation, it probably makes more sense for the task runtime to simply
run through the per-task resource tracking data and close things down
explicitly. In the "close things down explicitly" scenario, I *really* want
to avoid using the term finalization - that term is already bound for other
uses.

Regardless of the implementation, finalization (in the sense of 1) is *never
* prompt. In all practical implementations, resource reclamation *is* prompt,
up to release of certain low-level resources associated with hardware
devices or network connections. In some cases the release of those must be
delayed until timeouts are satisfied or the hardware state machine moves to
a suitable state for resource teardown. I think that's below the level
you're concerned about. It's "prompt enough".

By definition, I expect all finalization of task-local resources to
> happen within a task scope before it exits. The point is what semantics
> one should expect when one receives a "task X exited" indication: should
> all resources held by X always be finalized and reclaimed at this point?
> It seems so, just as we would expect from OS processes.
>

I think you are engaged in a layering confusion.

If a task exits voluntarily, then of course finalization (1 above) and
resource cleanup (2 above) can occur without difficulty. The finalization
phase will not be prompt, because finalization is never prompt, but I don't
think that really gets in the way of what you are saying. The contract
requirement is that finalization be completed before exit. Note, however,
that this may require several GC passes, because progressive finalizations
may release more heap resources, and the release of those resources, in
turn, may trigger further finalization. So there are some gory ugly details
there, and it's possible that an object requiring finalization remains
"live" until the lights are turned off for that task. Once the task is
done, that finalizer can't run. The "fix" for this is to make sure that the
voluntary exit conditions and behavior are well-specified.

BUT

If a task exits *involuntarily* - that is, it is *killed* - that is another
matter entirely. When we kill a task we are performing an operation at the
kernel layer of abstraction, and we are requiring, affirmatively, that no
further instructions in that task be executed. In consequence, finalization
(in the GC sense, which runs within the task, by definition) will not,
cannot, and must not be run. kernel-layer resource reclamation, or
comparable reclamation in the language-level task runtime, is fine and *
should* be run. Whether that reclamation is prompt is a consequence of the
underlying (kernel or language) runtime implementation. Your expectation of
promptness is reasonable, and I agree that it's good policy and good
practice, but it's not really something that the next layer up (the task
layer) is entitled to specify.


Jonathan
_______________________________________________
bitc-dev mailing list
[email protected]
http://www.coyotos.org/mailman/listinfo/bitc-dev

Reply via email to