summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKeith Bostic <keith@wiredtiger.com>2014-12-24 11:15:21 -0500
committerKeith Bostic <keith@wiredtiger.com>2014-12-24 11:15:21 -0500
commitbaa157b40673c027acf1ddcb99fedb848a660885 (patch)
treea69a301ed798ffd3bfd7b533cb8a8cfbdfcb2674 /src
parentbc7ed41d8e3d9c268c0d57600a36d32c98bdf8b0 (diff)
downloadmongo-baa157b40673c027acf1ddcb99fedb848a660885.tar.gz
Add wiredtiger_strerror_r, a thread-safe version of wiredtiger_strerror,
which allows us to support Windows' errors where we have to allocate a buffer to get the error string.
Diffstat (limited to 'src')
-rw-r--r--src/conn/api_strerror.c56
-rw-r--r--src/include/extern.h1
-rw-r--r--src/include/wiredtiger.in19
-rw-r--r--src/os_posix/os_errno.c27
-rw-r--r--src/os_win/os_errno.c27
5 files changed, 108 insertions, 22 deletions
diff --git a/src/conn/api_strerror.c b/src/conn/api_strerror.c
index caf536b24f7..5cabe55d3f6 100644
--- a/src/conn/api_strerror.c
+++ b/src/conn/api_strerror.c
@@ -4,40 +4,60 @@
/*
* wiredtiger_strerror --
- * Return a string for any error value.
+ * Return a string for any error value in a static buffer.
*/
const char *
wiredtiger_strerror(int error)
{
- static char errbuf[64];
- char *p;
+ static char buf[128];
- if (error == 0)
- return ("Successful return: 0");
+ if (wiredtiger_strerror_r(error, buf, sizeof(buf)) != 0)
+ (void)snprintf(buf, sizeof(buf), "error return: %d", error);
+ return (buf);
+}
+
+/*
+ * wiredtiger_strerror_r --
+ * Return a string for any error value, thread-safe version.
+ */
+int
+wiredtiger_strerror_r(int error, char *buf, size_t buflen)
+{
+ const char *p;
+
+ /* Require at least 2 bytes, printable character and trailing nul. */
+ if (buflen < 2)
+ return (ENOMEM);
switch (error) {
+ case 0:
+ p = "Successful return: 0";
+ break;
case WT_ROLLBACK:
- return ("WT_ROLLBACK: conflict between concurrent operations");
+ p = "WT_ROLLBACK: conflict between concurrent operations";
+ break;
case WT_DUPLICATE_KEY:
- return ("WT_DUPLICATE_KEY: attempt to insert an existing key");
+ p = "WT_DUPLICATE_KEY: attempt to insert an existing key";
+ break;
case WT_ERROR:
- return ("WT_ERROR: non-specific WiredTiger error");
+ p = "WT_ERROR: non-specific WiredTiger error";
+ break;
case WT_NOTFOUND:
- return ("WT_NOTFOUND: item not found");
+ p = "WT_NOTFOUND: item not found";
+ break;
case WT_PANIC:
- return ("WT_PANIC: WiredTiger library panic");
+ p = "WT_PANIC: WiredTiger library panic";
+ break;
case WT_RESTART:
- return ("WT_RESTART: restart the operation (internal)");
- default:
- if (error > 0 && (p = strerror(error)) != NULL)
- return (p);
+ p = "WT_RESTART: restart the operation (internal)";
break;
+ default:
+ return (__wt_strerror_r(error, buf, buflen));
}
/*
- * !!!
- * Not thread-safe, but this is never supposed to happen.
+ * Return success if anything printed (we checked if the buffer had
+ * space for at least one character).
*/
- (void)snprintf(errbuf, sizeof(errbuf), "Unknown error: %d", error);
- return (errbuf);
+ return (snprintf(buf, buflen, "%s", p) > 0 ? 0 : ENOMEM);
}
diff --git a/src/include/extern.h b/src/include/extern.h
index 056058f3828..b5c71aa7c15 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -431,6 +431,7 @@ extern int __wt_dlopen(WT_SESSION_IMPL *session, const char *path, WT_DLH **dlhp
extern int __wt_dlsym(WT_SESSION_IMPL *session, WT_DLH *dlh, const char *name, int fail, void *sym_ret);
extern int __wt_dlclose(WT_SESSION_IMPL *session, WT_DLH *dlh);
extern int __wt_errno(void);
+extern int __wt_strerror_r(int error, char *buf, size_t buflen);
extern int __wt_exist(WT_SESSION_IMPL *session, const char *filename, int *existp);
extern void __wt_fallocate_config(WT_SESSION_IMPL *session, WT_FH *fh);
extern int __wt_fallocate( WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t offset, wt_off_t len);
diff --git a/src/include/wiredtiger.in b/src/include/wiredtiger.in
index 075514e02b4..20991278440 100644
--- a/src/include/wiredtiger.in
+++ b/src/include/wiredtiger.in
@@ -2019,15 +2019,26 @@ int wiredtiger_open(const char *home,
WT_CONNECTION **connectionp);
/*!
- * Return information about an error as a string; wiredtiger_strerror is a
- * superset of the ISO C99/POSIX 1003.1-2001 function strerror.
+ * Return information about a WiredTiger error as a string, not thread-safe.
*
* @snippet ex_all.c Display an error
*
- * @param err a return value from a WiredTiger, C library or POSIX function
+ * @param error a return value from a WiredTiger call
* @returns a string representation of the error
*/
-const char *wiredtiger_strerror(int err);
+const char *wiredtiger_strerror(int error);
+
+/*!
+ * Return information about a WiredTiger error as a string, thread-safe version.
+ *
+ * @snippet ex_all.c Display an error thread safe
+ *
+ * @param error a return value from a WiredTiger call
+ * @param buf a buffer of at least \c buflen bytes
+ * @param buflen the length of the buffer
+ * @returns zero for success, non-zero to indicate an error.
+ */
+int wiredtiger_strerror_r(int error, char *buf, size_t buflen);
#if !defined(SWIG)
/*!
diff --git a/src/os_posix/os_errno.c b/src/os_posix/os_errno.c
index 9290f7d651f..b0cb288ea74 100644
--- a/src/os_posix/os_errno.c
+++ b/src/os_posix/os_errno.c
@@ -20,3 +20,30 @@ __wt_errno(void)
*/
return (errno == 0 ? WT_ERROR : errno);
}
+
+/*
+ * __wt_strerror_r --
+ * POSIX implementation of strerror_r.
+ */
+int
+__wt_strerror_r(int error, char *buf, size_t buflen)
+{
+ char *p;
+
+ /* Require at least 2 bytes, printable character and trailing nul. */
+ if (buflen < 2)
+ return (ENOMEM);
+
+ /*
+ * POSIX errors are non-negative integers, copy the string into the
+ * user's buffer. Return success if anything printed (we checked if
+ * the buffer had space for at least one character).
+ */
+ if (error > 0 &&
+ (p = strerror(error)) != NULL && snprintf(buf, buflen, "%s", p) > 0)
+ return (0);
+
+ /* Fallback to a generic message, then guess it's a memory problem. */
+ return (
+ snprintf(buf, buflen, "error return: %d", error) > 0 ? 0 : ENOMEM);
+}
diff --git a/src/os_win/os_errno.c b/src/os_win/os_errno.c
index ce50106b0cc..856db1ae96d 100644
--- a/src/os_win/os_errno.c
+++ b/src/os_win/os_errno.c
@@ -25,3 +25,30 @@ __wt_errno(void)
return (err == ERROR_SUCCESS ? WT_ERROR : err);
}
+
+/*
+ * __wt_strerror_r --
+ * Windows implementation of strerror_r.
+ */
+int
+__wt_strerror_r(int error, char *buf, size_t buflen)
+{
+ char *p;
+
+ /* Require at least 2 bytes, printable character and trailing nul. */
+ if (buflen < 2)
+ return (ENOMEM);
+
+ /*
+ * POSIX errors are non-negative integers, copy the string into the
+ * user's buffer. Return success if anything printed (we checked if
+ * the buffer had space for at least one character).
+ */
+ if (error > 0 &&
+ (p = strerror(error)) != NULL && snprintf(buf, buflen, "%s", p) > 0)
+ return (0);
+
+ /* Fallback to a generic message, then guess it's a memory problem. */
+ return (
+ snprintf(buf, buflen, "error return: %d", error) > 0 ? 0 : ENOMEM);
+}