Re: NS_FAILED, NS_SUCCESS, and nsresult return values: suggested guidelines?

Mark Hammond <[email protected]> Sat, 14 Dec 2002 12:20:42 +1100
Newsgroups gmane.comp.mozilla.devel.xpcom
Organization Another Netscape Collabra Server User
Message-ID <[email protected]>
Nathan Kurz wrote:
> I'm new to Mozilla and rapidly learning about XPCOM.  I'm trying to
> figure out what the suggested guidelines are for the use of nsresult
> return values.  The particular case that confuses me is what to do
> when the result is not an XPCOM error (NS_ERROR_NOT_IMPLEMENTED), not
> a application error (NS_ERROR_OUT_OF_MEMORY), but an expected case
> that is a configured policy.
> 
> I'm working on some changes to the PAC proxy code to allow it to say
> that it to deny a given URL, basically allowing it to proxy it to a
> black hole without the ensuing problems of actually sending a request
> to the black hole.  I'm not sure how this should signal to a caller
> that 1) the request should not be completed, but 2) this is by design
> and shouldn't be treated as an application error.  Ignoring the
> question of whether a proxy should be really be doing this, am I
> allowed to do this by return value, or should this really use some
> other means?
> 
> The content-policy code does very similar things, but I'm not sure if
> it sets a good example. Take for example this code in
> nsImageFrame.cpp::RealLoadImage():
>   1979   if (aCheckContentPolicy)
>   1980     if (!CanLoadImage(realURI)) return NS_ERROR_FAILURE;
> Is this a good pattern to follow?  Or is this better as
> NS_ERROR_CONTENT_POLICY?  Or (with changes to caller)
> NS_SUCCESS_POLICY_BLOCKED?  Or does proper procedure demand that one
> return NS_OK and somehow signal the blockage by other means?
> 
> Or taking it from the callers point of view, is it good practice to
> analyze the result value one receives by any means other than
> NS_FAILED() or NS_SUCCESS()?
>    if (NS_FAILED(rv) && rv == NS_ERROR_TEMPORARY) 
>        try call again
>    else
>        return rv
> Is this acceptable, or considered bad form: "you takes your lumps"? 
> What about checking for a particular flavor of NS_SUCCESS? Is this
> more or less reasonable?
> 
> On a related note, what should one do with an NS_FAILED(rv) that one
> is not going to try to handle.  Like this code in
> imgLoader::LoadImage():
>   448     rv = NewImageChannel(...)
>   454     if (NS_FAILED(rv))
>   455       return NS_ERROR_FAILURE;
> I'd like to propagate NS_ERROR_PROXY_DENIED through this layer, but it
> obviously doesn't want me to.  Is changing the rv to a generic error
> considered a good way to protect ones caller from a what is
> potentially a module specific error code, or is it meddling in others
> affairs?  In general, should there be an expectation that NS_FAILED
> rv's will be propagated upwards until they are handled?
> 
> I would appreciate guidance.  The code itself seems to vary greatly in
> the choices it makes, and I haven't found any sort of XPCOM style
> guide that answers these questions.  Thanks for any pointers you can
> provide me.

Check out nsError.h.  Like MS-COM, it defines that some result codes are 
errors, and some are not.  All codes with the MSB set are considered 
errors.  From that .h:

#define NS_FAILED(_nsresult) ((_nsresult) & 0x80000000)
#define NS_SUCCEEDED(_nsresult) (!((_nsresult) & 0x80000000))

Thus, it is important that you use NS_FAILED() and NS_SUCCEEDED() rather 
than explicitly checking for non-zero.  NS_OK is but one "success" value.

On the other hand, Python will currently lose this nsresult value - the 
bindings throw the value away if it is not an error code.

Mark.