summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--APRDesign144
-rw-r--r--include/apr_errno.h269
-rw-r--r--include/arch/unix/misc.h1
-rw-r--r--include/arch/unix/networkio.h3
-rw-r--r--include/arch/win32/misc.h1
-rw-r--r--misc/unix/Makefile.in2
-rw-r--r--misc/unix/misc.h1
-rw-r--r--network_io/unix/networkio.h3
-rw-r--r--network_io/unix/sockets.c2
-rw-r--r--network_io/unix/sockopt.c29
10 files changed, 182 insertions, 273 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.
+
diff --git a/include/apr_errno.h b/include/apr_errno.h
index 8d0ece02d..9d7d20fef 100644
--- a/include/apr_errno.h
+++ b/include/apr_errno.h
@@ -62,29 +62,24 @@
extern "C" {
#endif /* __cplusplus */
-/* Define four layers of status code offsets so that we don't interfere
- * with the predefined errno codes on the operating system. Codes beyond
+/* APR_OS_START_ERROR is where the APR specific error values should start.
+ * APR_OS_START_STATUS is where the APR specific status codes should start.
* APR_OS_START_USEERR are reserved for applications that use APR that
- * layer their own error codes along with APR's.
+ * layer their own error codes along with APR's.
+ * APR_OS_START_SYSERR should be used for system error values on
+ * each platform.
*/
-#ifndef APR_OS_START_ERROR
-#define APR_OS_START_ERROR 4000
-#endif
-#ifndef APR_OS_START_STATUS
-#define APR_OS_START_STATUS (APR_OS_START_ERROR + 500)
-#endif
-#ifndef APR_OS_START_SYSERR
-#define APR_OS_START_SYSERR (APR_OS_START_STATUS + 500)
-#endif
-#ifndef APR_OS_START_USEERR
-#define APR_OS_START_USEERR (APR_OS_START_SYSERR + 500)
-#endif
+#define APR_OS_START_ERROR 1000
+#define APR_OS_START_STATUS (APR_OS_START_ERROR + 500)
+#define APR_OS_START_USEERR (APR_OS_START_STATUS + 500)
+#define APR_OS_START_CANONERR (APR_OS_START_USEERR + 500)
+#define APR_OS_START_SYSERR (APR_OS_START_CANONERR + 500)
-/* If this definition of APRStatus changes, then we can remove this, but right
- * now, the decision was to use an errno-like implementation.
- */
typedef int ap_status_t;
+int ap_canonical_error(ap_status_t err);
+const char *ap_strerror(ap_status_t err);
+
#define APR_SUCCESS 0
/* APR ERROR VALUES */
@@ -144,310 +139,106 @@ typedef int ap_status_t;
*/
#define APR_EMISMATCH (APR_OS_START_STATUS + 18)
-/*
- * APR equivalents to what should be standard errno codes.
- */
#ifdef EACCES
#define APR_EACCES EACCES
#else
-#define APR_EACCES (APR_OS_START_SYSERR + 0)
+#define APR_EACCES (APR_OS_START_CANONERR + 1)
#endif
#ifdef EEXIST
#define APR_EEXIST EEXIST
#else
-#define APR_EEXIST (APR_OS_START_SYSERR + 1)
-#endif
-
-#ifdef EISDIR
-#define APR_EISDIR EISDIR
-#else
-#define APR_EISDIR (APR_OS_START_SYSERR + 2)
+#define APR_EEXIST (APR_OS_START_CANONERR + 12)
#endif
#ifdef ENAMETOOLONG
#define APR_ENAMETOOLONG ENAMETOOLONG
#else
-#define APR_ENAMETOOLONG (APR_OS_START_SYSERR + 3)
+#define APR_ENAMETOOLONG (APR_OS_START_CANONERR + 13)
#endif
#ifdef ENOENT
#define APR_ENOENT ENOENT
#else
-#define APR_ENOENT (APR_OS_START_SYSERR + 4)
+#define APR_ENOENT (APR_OS_START_CANONERR + 14)
#endif
#ifdef ENOTDIR
#define APR_ENOTDIR ENOTDIR
#else
-#define APR_ENOTDIR (APR_OS_START_SYSERR + 5)
-#endif
-
-#ifdef ENXIO
-#define APR_ENXIO ENXIO
-#else
-#define APR_ENXIO (APR_OS_START_SYSERR + 6)
-#endif
-
-#ifdef ENODEV
-#define APR_ENODEV ENODEV
-#else
-#define APR_ENODEV (APR_OS_START_SYSERR + 7)
-#endif
-
-#ifdef EROFS
-#define APR_EROFS EROFS
-#else
-#define APR_EROFS (APR_OS_START_SYSERR + 8)
-#endif
-
-#ifdef ETXTBSY
-#define APR_ETXTBSY ETXTBSY
-#else
-#define APR_ETXTBSY (APR_OS_START_SYSERR + 9)
-#endif
-
-#ifdef EFAULT
-#define APR_EFAULT EFAULT
-#else
-#define APR_EFAULT (APR_OS_START_SYSERR + 10)
-#endif
-
-#ifdef ELOOP
-#define APR_ELOOP ELOOP
-#else
-#define APR_ELOOP (APR_OS_START_SYSERR + 11)
+#define APR_ENOTDIR (APR_OS_START_CANONERR + 15)
#endif
#ifdef ENOSPC
#define APR_ENOSPC ENOSPC
#else
-#define APR_ENOSPC (APR_OS_START_SYSERR + 12)
+#define APR_ENOSPC (APR_OS_START_CANONERR + 16)
#endif
#ifdef ENONOMEM
#define APR_ENOMEM ENOMEM
#else
-#define APR_ENOMEM (APR_OS_START_SYSERR + 13)
+#define APR_ENOMEM (APR_OS_START_CANONERR + 17)
#endif
#ifdef EMFILE
#define APR_EMFILE EMFILE
#else
-#define APR_EMFILE (APR_OS_START_SYSERR + 14)
+#define APR_EMFILE (APR_OS_START_CANONERR + 18)
#endif
#ifdef ENFILE
#define APR_ENFILE ENFILE
#else
-#define APR_ENFILE (APR_OS_START_SYSERR + 15)
+#define APR_ENFILE (APR_OS_START_CANONERR + 19)
#endif
#ifdef EBADF
#define APR_EBADF EBADF
#else
-#define APR_EBADF (APR_OS_START_SYSERR + 16)
-#endif
-
-#ifdef EPERM
-#define APR_EPERM EPERM
-#else
-#define APR_EPERM (APR_OS_START_SYSERR + 17)
-#endif
-
-#ifdef EIO
-#define APR_EIO EIO
-#else
-#define APR_EIO (APR_OS_START_SYSERR + 18)
+#define APR_EBADF (APR_OS_START_CANONERR + 110)
#endif
#ifdef EINVAL
#define APR_EINVAL EINVAL
#else
-#define APR_EINVAL (APR_OS_START_SYSERR + 19)
-#endif
-
-#ifdef ENOEMPTY
-#define APR_ENOEMPTY ENOEMPTY
-#else
-#define APR_ENOEMPTY (APR_OS_START_SYSERR + 20)
-#endif
-
-#ifdef EBUSY
-#define APR_EBUSY EBUSY
-#else
-#define APR_EBUSY (APR_OS_START_SYSERR + 21)
+#define APR_EINVAL (APR_OS_START_CANONERR + 111)
#endif
#ifdef ESPIPE
#define APR_ESPIPE ESPIPE
#else
-#define APR_ESPIPE (APR_OS_START_SYSERR + 22)
-#endif
-
-#ifdef EIDRM
-#define APR_EIDRM EIDRM
-#else
-#define APR_EIDRM (APR_OS_START_SYSERR + 23)
-#endif
-
-#ifdef ERANGE
-#define APR_ERANGE ERANGE
-#else
-#define APR_ERANGE (APR_OS_START_SYSERR + 24)
-#endif
-
-#ifdef E2BIG
-#define APR_E2BIG E2BIG
-#else
-#define APR_E2BIG (APR_OS_START_SYSERR + 25)
+#define APR_ESPIPE (APR_OS_START_CANONERR + 112)
#endif
#ifdef EAGAIN
#define APR_EAGAIN EAGAIN
#else
-#define APR_EAGAIN (APR_OS_START_SYSERR + 26)
-#endif
-
-#ifdef EFBIG
-#define APR_EFBIG EFBIG
-#else
-#define APR_EFBIG (APR_OS_START_SYSERR + 27)
+#define APR_EAGAIN (APR_OS_START_CANONERR + 13)
#endif
#ifdef EINTR
#define APR_EINTR EINTR
#else
-#define APR_EINTR (APR_OS_START_SYSERR + 28)
-#endif
-
-#ifdef EDEADLK
-#define APR_EDEADLK EDEADLK
-#else
-#define APR_EDEADLK (APR_OS_START_SYSERR + 29)
-#endif
-
-#ifdef ENOLCK
-#define APR_ENOLCK ENOLCK
-#else
-#define APR_ENOLCK (APR_OS_START_SYSERR + 30)
-#endif
-
-#ifdef EWOULDBLOCK
-#define APR_EWOULDBLOCK EWOULDBLOCK
-#else
-#define APR_EWOULDBLOCK (APR_OS_START_SYSERR + 31)
-#endif
-
-#ifdef EPROTONOSUPPORT
-#define APR_EPROTONOSUPPORT EPROTONOSUPPORT
-#else
-#define APR_EPROTONOSUPPORT (APR_OS_START_SYSERR + 32)
+#define APR_EINTR (APR_OS_START_CANONERR + 14)
#endif
#ifdef ENOTSOCK
#define APR_ENOTSOCK ENOTSOCK
#else
-#define APR_ENOTSOCK (APR_OS_START_SYSERR + 33)
-#endif
-
-#ifdef ENOTCONN
-#define APR_ENOTCONN ENOTCONN
-#else
-#define APR_ENOTCONN (APR_OS_START_SYSERR + 34)
-#endif
-
-#ifdef EOPNOTSUPP
-#define APR_EOPNOTSUPP EOPNOTSUPP
-#else
-#define APR_EOPNOTSUPP (APR_OS_START_SYSERR + 35)
-#endif
-
-/* never use h_errno values as-is because doing so makes them
- * indistinguishable from errno values
- * APR_EHOSTNOTFOUND corresponds to HOST_NOT_FOUND
- * APR_ENODATA corresponds to NO_DATA
- * APR_ENOADDRESS corresponds to NO_ADDRESS
- * APR_ENORECOVERY corresponds to NO_RECOVERY
- */
-#define APR_EHOSTNOTFOUND (APR_OS_START_SYSERR + 36)
-
-#define APR_ENODATA (APR_OS_START_SYSERR + 37)
-
-#define APR_ENOADDRESS (APR_OS_START_SYSERR + 38)
-
-#define APR_ENORECOVERY (APR_OS_START_SYSERR + 39)
-
-#ifdef EISCONN
-#define APR_EISCONN EISCONN
-#else
-#define APR_EISCONN (APR_OS_START_SYSERR + 40)
-#endif
-
-#ifdef ETIMEDOUT
-#define APR_ETIMEDOUT ETIMEDOUT
-#else
-#define APR_ETIMEDOUT (APR_OS_START_SYSERR + 41)
+#define APR_ENOTSOCK (APR_OS_START_CANONERR + 15)
#endif
#ifdef ECONNREFUSED
#define APR_ECONNREFUSED ECONNREFUSED
#else
-#define APR_ECONNREFUSED (APR_OS_START_SYSERR + 42)
-#endif
-
-#ifdef ENETUNREACH
-#define APR_ENETUNREACH ENETUNREACH
-#else
-#define APR_ENETUNREACH (APR_OS_START_SYSERR + 43)
-#endif
-
-#ifdef EADDRINUSE
-#define APR_EADDRINUSE EADDRINUSE
-#else
-#define APR_EADDRINUSE (APR_OS_START_SYSERR + 44)
+#define APR_ECONNREFUSED (APR_OS_START_CANONERR + 16)
#endif
#ifdef EINPROGRESS
#define APR_EINPROGRESS EINPROGRESS
#else
-#define APR_EINPROGRESS (APR_OS_START_SYSERR + 45)
-#endif
-
-#ifdef EALREADY
-#define APR_EALREADY EALREADY
-#else
-#define APR_EALREADY (APR_OS_START_SYSERR + 46)
-#endif
-
-#ifdef EAFNOSUPPORT
-#define APR_EAFNOSUPPORT EAFNOSUPPORT
-#else
-#define APR_EAFNOSUPPORT (APR_OS_START_SYSERR + 47)
-#endif
-
-#ifdef ENOPROTOOPT
-#define APR_ENOPROTOOPT ENOPROTOOPT
-#else
-#define APR_ENOPROTOOPT (APR_OS_START_SYSERR + 48)
-#endif
-
-#ifdef ENOCHILD
-#define APR_ENOCHILD ENOCHILD
-#else
-#define APR_ENOCHILD (APR_OS_START_SYSERR + 49)
-#endif
-
-#ifdef ESRCH
-#define APR_ESRCH ESRCH
-#else
-#define APR_ESRCH (APR_OS_START_SYSERR + 50)
-#endif
-
-#ifdef ENOTSUP
-#define APR_ENOTSUP ENOTSUP
-#else
-#define APR_ENOTSUP (APR_OS_START_SYSERR + 51)
+#define APR_EINPROGRESS (APR_OS_START_CANONERR + 17)
#endif
#ifdef __cplusplus
diff --git a/include/arch/unix/misc.h b/include/arch/unix/misc.h
index dfa7ae62f..dfe0413a9 100644
--- a/include/arch/unix/misc.h
+++ b/include/arch/unix/misc.h
@@ -61,6 +61,7 @@
#include "apr_pools.h"
#include "apr_getopt.h"
#include "apr_thread_proc.h"
+#include "apr_errno.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
diff --git a/include/arch/unix/networkio.h b/include/arch/unix/networkio.h
index 98fbda7e9..6ebb096e6 100644
--- a/include/arch/unix/networkio.h
+++ b/include/arch/unix/networkio.h
@@ -57,6 +57,7 @@
#include "apr_config.h"
#include "apr_network_io.h"
+#include "apr_errno.h"
#include "apr_general.h"
#include "apr_lib.h"
@@ -136,7 +137,5 @@ struct ap_pollfd_t {
ap_int16_t get_event(ap_int16_t);
ap_int16_t get_revent(ap_int16_t);
-ap_status_t status_from_res_error(int);
-
#endif /* ! NETWORK_IO_H */
diff --git a/include/arch/win32/misc.h b/include/arch/win32/misc.h
index dfa7ae62f..dfe0413a9 100644
--- a/include/arch/win32/misc.h
+++ b/include/arch/win32/misc.h
@@ -61,6 +61,7 @@
#include "apr_pools.h"
#include "apr_getopt.h"
#include "apr_thread_proc.h"
+#include "apr_errno.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
diff --git a/misc/unix/Makefile.in b/misc/unix/Makefile.in
index 105f10e48..90308359c 100644
--- a/misc/unix/Makefile.in
+++ b/misc/unix/Makefile.in
@@ -15,7 +15,7 @@ INCLUDES=-I$(INCDIR1) -I$(INCDIR2) -I.
#LIB=libmisc.a
-OBJS=start.o getopt.o otherchild.o
+OBJS=start.o getopt.o otherchild.o error.o
.c.o:
$(CC) $(CFLAGS) -c $(INCLUDES) $<
diff --git a/misc/unix/misc.h b/misc/unix/misc.h
index dfa7ae62f..dfe0413a9 100644
--- a/misc/unix/misc.h
+++ b/misc/unix/misc.h
@@ -61,6 +61,7 @@
#include "apr_pools.h"
#include "apr_getopt.h"
#include "apr_thread_proc.h"
+#include "apr_errno.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
diff --git a/network_io/unix/networkio.h b/network_io/unix/networkio.h
index 98fbda7e9..6ebb096e6 100644
--- a/network_io/unix/networkio.h
+++ b/network_io/unix/networkio.h
@@ -57,6 +57,7 @@
#include "apr_config.h"
#include "apr_network_io.h"
+#include "apr_errno.h"
#include "apr_general.h"
#include "apr_lib.h"
@@ -136,7 +137,5 @@ struct ap_pollfd_t {
ap_int16_t get_event(ap_int16_t);
ap_int16_t get_revent(ap_int16_t);
-ap_status_t status_from_res_error(int);
-
#endif /* ! NETWORK_IO_H */
diff --git a/network_io/unix/sockets.c b/network_io/unix/sockets.c
index 8761e9047..51c59e446 100644
--- a/network_io/unix/sockets.c
+++ b/network_io/unix/sockets.c
@@ -232,7 +232,7 @@ ap_status_t ap_connect(ap_socket_t *sock, char *hostname)
return APR_ENOTSOCK;
}
if (!hp) {
- return status_from_res_error(h_errno);
+ return (h_errno + APR_OS_START_SYSERR);
}
memcpy((char *)&sock->remote_addr->sin_addr, hp->h_addr_list[0], hp->h_length);
diff --git a/network_io/unix/sockopt.c b/network_io/unix/sockopt.c
index 0306772f1..ff73b5539 100644
--- a/network_io/unix/sockopt.c
+++ b/network_io/unix/sockopt.c
@@ -208,33 +208,6 @@ ap_status_t ap_get_remote_hostname(char **name, ap_socket_t *sock)
}
/* XXX - Is referencing h_errno threadsafe? */
- return status_from_res_error(h_errno);
-}
-
-ap_status_t status_from_res_error(int herr)
-{
- ap_status_t status;
- switch(herr) {
- case HOST_NOT_FOUND:
- status = APR_EHOSTNOTFOUND;
- break;
- case TRY_AGAIN:
- status = APR_EAGAIN;
- break;
- case NO_RECOVERY:
- status = APR_ENORECOVERY;
- break;
- case NO_ADDRESS:
- status = APR_ENOADDRESS;
- break;
-#if defined(NO_DATA) && (NO_ADDRESS != NO_DATA)
- case NO_DATA:
-#endif
- status = APR_ENODATA;
- break;
- default:
- status = APR_ENORECOVERY;
- }
- return status;
+ return (h_errno + APR_OS_START_SYSERR);
}