summaryrefslogtreecommitdiff
path: root/APRDesign
diff options
context:
space:
mode:
authorRyan Bloom <rbb@apache.org>2000-04-07 14:16:29 +0000
committerRyan Bloom <rbb@apache.org>2000-04-07 14:16:29 +0000
commit204e6444093102f6ddcd2d2ddcef44f15d409831 (patch)
tree4953dedaa06de7117e8c2ffef42049c264ccc025 /APRDesign
parent374bc55649c541cf1872ec60a6ffb1974c1fb336 (diff)
downloadapr-204e6444093102f6ddcd2d2ddcef44f15d409831.tar.gz
Update the error handling in APR. This includes the docs in APRDesign.
Any platform that doesn't use errno as error codes are not working properly and will need to be modified. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@59814 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'APRDesign')
-rw-r--r--APRDesign144
1 files changed, 144 insertions, 0 deletions
diff --git a/APRDesign b/APRDesign
index e41a02bc9..fe5109a3a 100644
--- a/APRDesign
+++ b/APRDesign
@@ -179,3 +179,147 @@ The format for the comment block is:
*/
For an actual example, look at any function in the fileio/unix directory.
+
+APR Error reporting
+
+Most APR functions should return an ap_status_t type. The only time an
+APR function does not return an ap_status_t is if it absolutly CAN NOT
+fail. Examples of this would be filling out an array when you know you are
+not beyond the array's range. If it cannot fail on your platform, but it
+could conceivably fail on another platform, it should return an ap_status_t.
+Unless you are sure, return an ap_status_t. :-)
+
+All platform return errno values unchanged. Each platform can also have
+one system error type, which can be returned after an offset is added.
+There are five types of error values in APR, each with it's own offset.
+
+ Name Purpose
+0) This is 0 for all platforms and isn't really defined
+ anywhere, but it is the offset for errno values.
+ (This has no name because it isn't actually defined,
+ but completeness we are discussing it here).
+1) APR_OS_START_ERROR This is platform dependant, and is the offset at which
+ APR errors start to be defined. (Canonical error
+ values are also defined in this section. [Canonical
+ error values are discussed later]).
+2) APR_OS_START_STATUS This is platform dependant, and is the offset at which
+ APR status values start.
+4) APR_OS_START_USEERR This is platform dependant, and is the offset at which
+ APR apps can begin to add their own error codes.
+3) APR_OS_START_SYSERR This is platform dependant, and is the offset at which
+ system error values begin.
+
+All of these definitions can be found in apr_errno.h for all platforms. When
+an error occurs in an APR function, the function must return an error code.
+If the error occurred in a system call and that system call uses errno to
+report an error, then the code is returned unchanged. For example:
+
+ if (open(fname, oflags, 0777) < 0)
+ return errno;
+
+
+The next place an error can occur is a system call that uses some error value
+other than the primary error value on a platform. This can also be handled
+by APR applications. For example:
+
+ if (CreateFile(fname, oflags, sharemod, NULL,
+ createflags, attributes,0) == INVALID_HANDLE_VALUE
+ return (GetLAstError() + APR_OS_START_SYSERR);
+
+These two examples implement the same function for two different platforms.
+Obviously even if the underlying problem is the same on both platforms, this
+will result in two different error codes being returned. This is OKAY, and
+is correct for APR. APR relies on the fact that most of the time an error
+occurs, the program logs the error and continues, it does not try to
+programatically solve the problem. This does not mean we have not provided
+support for programmatically solving the problem, it just isn't the default
+case. We'll get to how this problem is solved in a little while.
+
+If the error occurs in an APR function but it is not due to a system call,
+but it is actually an APR error or just a status code from APR, then the
+appropriate code should be returned. These codes are defined in apr_errno.h
+and are self explanatory.
+
+No APR code should ever return a code between APR_OS_START_USEERR and
+APR_OS_START_SYSERR, those codes are reserved for APR applications.
+
+To programmatically correct an error in a running application, the error codes
+need to be consistent across platforms. This should make sense. To get
+consistent error codes, APR provides a function ap_canonicalize_error().
+This function will take as input any ap_status_t value, and return a small
+subset of canonical APR error codes. These codes will be equivalent to
+Unix errno's. Why is it a small subset? Because we don't want to try to
+convert everything in the first pass. As more programs require that more
+error codes are converted, they will be added to this function.
+
+Why did APR take this approach? There are two ways to deal with error
+codes portably.
+
+1) return the same error code across all platforms. 2) return platform
+specific error codes and convert them when necessary.
+
+The problem with option number one is that it takes time to convert error
+codes to a common code, and most of the time programs want to just output
+an error string. If we convert all errors to a common subset, we have four
+steps to output an error string:
+
+ make syscall that fails
+ convert to common error code step 1
+ return common error code
+ check for success
+ call error output function step 2
+ convert back to system error step 3
+ output error string step 4
+
+By keeping the errors platform specific, we can output error strings in two
+steps.
+
+ make syscall that fails
+ return error code
+ check for success
+ call error output function step 1
+ output error string step 2
+
+Less often, programs change their execution based on what error was returned.
+This is no more expensive using option 2 and it is using option 1, but we
+put the onus of converting the error code on the programmer themselves.
+For example, using option 1:
+
+ make syscall that fails
+ convert to common error code
+ return common error code
+ decide execution basd on common error code
+
+Using option 2:
+
+ make syscall that fails
+ return error code
+ convert to common error code (using ap_canonicalize_error)
+ decide execution based on common error code
+
+Finally, there is one more operation on error codes. You can get a string
+that explains in human readable form what has happened. To do this using
+APR, call ap_strerror().
+
+On all platforms ap_strerror takes the form:
+
+char *ap_strerror(ap_status_t err)
+{
+ if (err < APR_OS_START_ERRNO2)
+ return (platform dependant error string generator)
+ if (err < APR_OS_START_ERROR)
+ return (platform dependant error string generator for
+ supplemental error values)
+ if (err < APR_OS_SYSERR)
+ return (APR generated error or status string)
+ if (err == 0)
+ return "No error was found"
+ else
+ return "APR doesn't understand this error value"
+}
+
+Notice, this does not handle canonicalized error values well. Those will
+return "APR doesn't understand this error value" on some platforms and
+an actual error string on others. To deal with this, just get the
+string before canonicalizing your error code.
+