Re: [c++-pthreads] Re: thread-safety definition
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [c++-pthreads] Re: thread-safety definition



David Abrahams wrote:

Ah. I see the problem. I believe that you neglected to file in
triplicate the official "List of all matters with which I disagree so
please don't shout when discussing them" form. Didn't you? ;-)
I filed.  It was *you* who neglected to check with the department of
archival non-shouting topic storage, wasn't it?
Aw, shoot. I forgot to pay the bill on my automatic update service, and it expired! Sorry 'bout that.

If you make cancellations behave sufficiently like an ordinary C++
exception (either of Nathan's or Jason's models would do that I think)
then it's neither "IMPOSSIBLE" nor even difficult.  A great deal of
thread-safe exception-safe C++ library code would behave perfectly
well under those conditions.

Well, it should be no surprise that this discussion has fragmented
into too many different little pathways for anyone to keep track of
them.

If cancel is implemented completely as a "full stature" C++ exception,
and none of the "exception safe" code does anything silly like
"catch(...)" without a re-throw, then, yes, it's likely to be
reasonably cancel-safe.
Even if only *some* of it does that, Nathan and Jason's models are
both likely to result in an eventual cancellation.
I need to start keeping a scorecard. Lessee here, Nathan's model I believe could be trivially characterized as "return failure status on any cancellation point until you hit a C++ function allowed to throw". This would apparently disable any cleanup operations involving cancellation points (they'd fail) at least prior to the first throw point -- and it's not precisely clear how the "pending cancel" state is to be managed even beyond that point. While it might eventually lead to cancellation, it won't reliably perform cleanup. This seems to me to be more complicated, less predictable, less compatible, and less reliable than simply using exceptions integrated with the existing POSIX cleanup mechanism.

Jason's model, putting together the puzzle pieces from various messages here, appears to be basing cancel on an ordinary ("finalizable") C++ exception, which would be raised by any and all cancellation points; but if the exception object were to be destroyed (by finalization), the "pending cancel" would (might?) be reasserted. I personally feel that it ought to be reasonable to finalize the cancel and continue operation. If that wasn't really what the application intended then it's an application error; but there are cases where it's arguably reasonable, and the capability falls naturally out of the model. Besides, "reasserting cancel" in all the right places and no other places sounds like one of those projects that ends up being a lot more subtle and error-prone than anyone ever expects. ;-)

(Though some code might need to be aware that an uncaught cancel
will terminate the thread rather than the process!)
Remember, we're talking about library code.  Usually it's only used
"on the inside" of threads so it doesn't care whether when it's
terminated, it's the process or only a thread.

But I was really responding to the ideas about turning cancel into a
return status
...only for 'C' functions which ordinarily have a return status and don't
throw...  did you miss that?

It doesn't matter. There are many problems lurking here, and only one of the more obvious is that this attempt to avoid breaking C code that depends on 'if (error) {cleanup(); return error;}' will still break if 'cleanup()' depends on any cancellation points... which in fact is quite likely if 'error' originates from a cancellation point (e.g., I/O). I also don't believe that a sufficient body of library code really follows the simple and direct 'if (error) return error;' pattern to make this strategy particularly useful even without the cleanup issues -- but that's a different matter. (It might actually be better if the pending cancel wasn't "sticky", since then the cleanup at least might succeed; but then you'll lose cancels all over the place, and that's definitely not acceptable. It's fine for a thread to CHOOSE not to accept a cancel, either by keeping cancellation disabled or by not calling a cancellation point; but it's not OK to lose a delivered cancel. You can declare this to be the application/library developer's job rather than the implementation's job -- but that just means all this "broken" C code that fails to propagate errors needs to be redesigned; and you haven't solved any real problem. That's the basic point: it needs to be analyzed and likely redesigned to be cancel-safe. You simply can't avoid that requirement.)

A) You cannot transparently make non cancel-safe C code cancel-safe, no matter how you try. B) Delivering cancellation as a C++ exception will make much (though not all) exception-safe C++ "translucently" cancel-safe. C) POSIX C cancel-safe code is already cancel-safe, but for an application containing mixed call stacks to remain cancel-safe, POSIX cleanup and C++ exceptions must be integrated into a single unwind; i.e., (by whatever name) basing both on a common exception library. D) There are no useful or interestingly large bodies of rigorously "cancel-safe" C code that are not POSIX cancel-safe.

In other words, cancel-as-exception, and pthread_cleanup_push as a C-based "try" extension, gives you all the cancel-safety you can reasonably expect without recoding (and likely redesign). That's all that's needed. No less will suffice, and any more is needless complication. Non cancel-safe code will continue to work just fine as long as it's NOT cancelled -- which ought to be no terrible restriction since it was clearly written in and for an environment where cancellation either did not exist or wasn't needed.

--
/--------------------[ David.Butenhof@xxxxxx ]--------------------\
| Hewlett-Packard Company       Tru64 UNIX & VMS Thread Architect |
|     My book: http://www.awl.com/cseng/titles/0-201-63392-2/     |
\----[ http://homepage.mac.com/dbutenhof/Threads/Threads.html ]---/