Version française
Home     About     Download     Resources     Contact us    
Browse thread
more patches (for Unix signal mask)
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Joerg Czeranski <jc@j...>
Subject: Are exceptions evil? (was: more patches)
This morning I rethought my patches under the shower and found another
bug (signals are not blocked while the handler is executed, if the
signal was caught with async_signal_mode == 0).

It's not difficult to fix, I'll do that later.  Even the signal
loss race condition can be fixed without too much thought.

But that's because signals are easy to control, they move down the
stack (for stacks growing down).  They won't bypass interrupted
functions, they only return to them after being handled.

Exceptions on the other hand go straight up the stack until they find
a handler, and then *immediately* invalidate the handler.
In a non-pure programming language like O'Caml this creates unavoidable
race conditions:

	let resource = acquire () in
	try
		use resource;
		release resource
	with e ->
		release resource;
		raise e

"release" is never called if two exceptions arrive at virtually
the same time, and neither if an exception arrives after the call
to "acquire", but before the "try".

N.b.: For me acquire is usually Unix.openfile, but it could as well
be a native O'Caml function with sideeffects (like "incr semaphore").

I think the fundamental reason for this problem is that exceptions
are thrown up the stack and not forward on the timeline of side effects.
They ought to skip new acquire calls, but never a release call for
a resource already acquired.

Is there anything that can be done about this?  Or does it require
wrapping all (relevant) side effects with monads?  Or am I missing
something?

regards,
joerch