krowitz@mitlns.BITNET ("DAVID_M_KROWITZ") (08/28/86)
I recently had a informative talk with Robert Stanzel of Apollo about the proper way to handle status codes on the Apollo (as a result of one of my numerous UCR's). He sent me a copy of this memo on the current method which is used to handle status codes which I thought might be useful to other people who are trying to write code which does fancy error-recovery so I have passed it along. -- David Krowitz This is the memo I mentioned on the phone. It's not directly relevant, but mentions some of the recognized problems with our status handling. On the use of "status_$t" OUT parameters in Streams =================================================== A general philosophy concerning status codes is that clients (callers) of subsystems (collection of procedures) should explicitly test ONLY for statuses that are defined to be returned by the subsystem. Further, any statuses that are NOT defined by the subsystem are not guaranteed to be stable across software releases. For example, the following is OK: stream_$get_rec( id, ..., st ); if ( status.subsys = stream_$subs ) and ( status.all = stream_$end_of_file ) then ... and both of the following are NOT OK: stream_$get_rec( id, ..., st ); if status.all = network_$xmit_failed then ... ----- stream_$get_rec( id, ..., st ); st.fail := false; if status.all = network_$xmit_failed then ... because the Streams subsystem includes "stream_$end_of_file" among its defined statuses but doesn't include "network_$xmit_failed". We recognize that documentation concerning status codes has been inadequate and that exactly what statuses are defined by a subsystem has been ill-defined. In particular, for some subsystems, the defined statuses are exactly those that appear in the subsystem's insert file; but for other subsystems, the defined statuses are those PLUS some other, ill-specified set. For example, "gpr_$open_bitmap_file" can return "gpr_$..." errors AND certain "name_$..." errors (e.g. "name_$not_found"). Another area of confusion has been the "fail" field in the "status_$t" record. The intent of is that if a returned status has the fail field set to "true", then all bets are off -- the subsystem is reporting that it got an unexpected error and the client is not allowed to make any inferences about the nature of the failure. Further, it is quite likely that the returned status will change across releases. As far as the Streams subsystem is concerned, our intent is that the defined Streams return statuses are exactly those codes defined in "streams.ins.pas". Checking for non-"stream_$" return statuses from "stream_$" calls is liable to produce unpredictable results across releases. Unfortunately, between sr8 and sr9, Streams' status behavior changed some. At sr8, "stream_$create" could return "name_$insufficient_rights" if you tried to create a file in a directory for which you didn't have "a" rights. At sr9, "stream_$create" returns that same status code BUT with the fail field set to "true". The change was a side-effect of Streams' being more careful to turn on the fail field in case it was returning a non-Streams status. The sr9 behavior is more correct than the sr8 behavior, but the truly correct behavior is for "stream_$create" to return "stream_$insufficient_rights" (with the fail field "false") in this case since it is a perfectly normal and expected event that clients might want to check for. To get around this problem and to avoid user's needing to change their code at the next release, callers of "stream_$create" should check the returned status in the following way: stream_$create( ..., st ); if ( ( st.subsys = stream_$subs ) and ( st.code = stream_$insufficient_rights ) ) or ( st.all = 16#800E0014 ) { name_$insufficient_rights + "fail" } then ... ------- ------