chromatic via RT wrote:
On Monday 15 September 2008 23:21:26 Christoph Otto wrote:

--- src/pmc/os.pmc      (revision 31173)
+++ src/pmc/os.pmc      (working copy)
@@ -31,9 +31,6 @@

 #include "parrot/parrot.h"

-/* XXX Check if we need to deallocate strerror strings */
-/* XXX apparently, strerror_r is thread-safe and should be used instead.*/
-
 static PMC *OS_PMC;
 pmclass OS singleton {

@@ -92,9 +89,8 @@
             RETURN(STRING *scwd);
         }
         else {
-            const char * const errmsg = strerror(errno);
             Parrot_ex_throw_from_c_args(interp, NULL,
EXCEPTION_EXTERNAL_ERROR, -                errmsg);
+                "%Ss", Parrot_strerror(interp, errno));
         }
     }

This pattern's almost common enough to tempt me to write Parrot_ex_throw_strerror().

-- c



It was also almost enough to make me write Parrot_strerror. This patch contains a file that I neglected to include with the previous one. Thanks to Andy Dougherty for catching that.
Index: src/ops/sys.ops
===================================================================
--- src/ops/sys.ops	(revision 31174)
+++ src/ops/sys.ops	(working copy)
@@ -66,13 +66,11 @@
 }
 
 op err(out STR) {
-  const char * const tmp = strerror(errno);
-  $1 = string_make(interp, tmp, strlen(tmp), "ascii", 0);
+  $1 = Parrot_strerror(interp, errno);
 }
 
 op err(out STR, in INT) {
-  const char * const tmp = strerror($2);
-  $1 = string_make(interp, tmp, strlen(tmp), "ascii", 0);
+  $1 = Parrot_strerror(interp, $2);
 }
 
 
Index: src/pmc/os.pmc
===================================================================
--- src/pmc/os.pmc	(revision 31174)
+++ src/pmc/os.pmc	(working copy)
@@ -31,9 +31,6 @@
 
 #include "parrot/parrot.h"
 
-/* XXX Check if we need to deallocate strerror strings */
-/* XXX apparently, strerror_r is thread-safe and should be used instead.*/
-
 static PMC *OS_PMC;
 pmclass OS singleton {
 
@@ -92,9 +89,8 @@
             RETURN(STRING *scwd);
         }
         else {
-            const char * const errmsg = strerror(errno);
             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+                "%Ss", Parrot_strerror(interp, errno));
         }
     }
 
@@ -118,9 +114,8 @@
 #endif
         string_cstring_free(cpath);
         if (error) {
-            char *errmsg = strerror(errno);
             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+                "%Ss", Parrot_strerror(interp, errno));
         }
     }
 
@@ -141,10 +136,9 @@
         int   error = stat(cpath, &info);
 
         if (error) {
-            const char * const errmsg = strerror(errno);
             string_cstring_free(cpath);
             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+                "%Ss", Parrot_strerror(interp, errno));
         }
 
         if (S_ISDIR(info.st_mode)) {
@@ -155,18 +149,16 @@
 #endif
             string_cstring_free(cpath);
             if (error) {
-                const char * const errmsg = strerror(errno);
                 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                    errmsg);
+                    "%Ss", Parrot_strerror(interp, errno));
             }
         }
         else {
             error = remove(cpath);
             string_cstring_free(cpath);
             if (error) {
-                const char * const errmsg = strerror(errno);
                 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                    errmsg);
+                    "%Ss", Parrot_strerror(interp, errno));
             }
         }
     }
@@ -192,9 +184,8 @@
 #endif
         string_cstring_free(cpath);
         if (error) {
-            const char * const errmsg = strerror(errno);
             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+                "%Ss", Parrot_strerror(interp, errno));
         }
     }
 
@@ -231,9 +222,8 @@
         string_cstring_free(cpath);
 
         if (error) {
-            const char * const errmsg = strerror(errno);
             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+                "%Ss", Parrot_strerror(interp, errno));
         }
         else {
             PMC * const array = pmc_new(interp, enum_class_FixedPMCArray);
@@ -296,9 +286,8 @@
         string_cstring_free(cpath);
 
         if (error) {
-            const char * const errmsg = strerror(errno);
             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+                "%Ss", Parrot_strerror(interp, errno));
         }
         else {
             PMC * const array = pmc_new(interp, enum_class_FixedPMCArray);
@@ -343,9 +332,8 @@
         string_cstring_free(cto);
 
         if (error) {
-            const char * const errmsg = strerror(errno);
             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+                "%Ss", Parrot_strerror(interp, errno));
         }
 #else
         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
@@ -373,9 +361,8 @@
         string_cstring_free(cto);
 
         if (error) {
-            const char * const errmsg = strerror(errno);
             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+                "%Ss", Parrot_strerror(interp, errno));
         }
 #else
         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INTERNAL_NOT_IMPLEMENTED,
@@ -427,9 +414,8 @@
         string_cstring_free(cpath);
 
         if (error) {
-            const char * const errmsg = strerror(errno);
             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+                "%Ss", Parrot_strerror(interp, errno));
         }
 #else
         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INTERNAL_NOT_IMPLEMENTED,
@@ -458,9 +444,8 @@
         string_cstring_free(cpath);
 
         if (!dir) {
-            const char * const errmsg = strerror(errno);
             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+                "%Ss", Parrot_strerror(interp, errno));
         }
 
         array = pmc_new(interp, enum_class_ResizableStringArray);
@@ -495,9 +480,8 @@
         string_cstring_free(cnewpath);
 
         if (ret < 0) {
-            const char * const errmsg = strerror(errno) ;
             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                "%s", errmsg);
+                "%Ss", Parrot_strerror(interp, errno));
         }
     }
 
Index: src/pmc/file.pmc
===================================================================
--- src/pmc/file.pmc	(revision 31174)
+++ src/pmc/file.pmc	(working copy)
@@ -22,10 +22,10 @@
 #  include <direct.h>
 #endif
 
+#define ERRBUF_SIZE 128
+
 #include "parrot/parrot.h"
 
-/* RT#46681 apparently, strerror_r is thread-safe and should be used instead.*/
-
 static PMC *File_PMC;
 pmclass File singleton {
 
@@ -73,9 +73,15 @@
 #endif
         string_cstring_free(cpath);
 
-        if (error)
+        if (error && errno == ENOENT) {
             RETURN(INTVAL 0);
+        }
+        else if (error) {
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_LIBRARY_ERROR, "%Ss",
+                    Parrot_strerror(INTERP, errno));
+        }
 
+
         RETURN(INTVAL 1);
     }
 
@@ -89,6 +95,7 @@
 
 */
 
+
     METHOD is_dir(STRING *path) {
         struct stat info;
         char *cpath = string_to_cstring(interp, path);
@@ -100,9 +107,8 @@
         string_cstring_free(cpath);
 
         if (error) {
-            char *errmsg = strerror(errno);
-            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_LIBRARY_ERROR, "%Ss",
+                    Parrot_strerror(INTERP, errno));
         }
 
         if (S_ISDIR(info.st_mode))
@@ -132,9 +138,8 @@
         string_cstring_free(cpath);
 
         if (error) {
-            char *errmsg = strerror(errno);
-            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_LIBRARY_ERROR, "%Ss",
+                    Parrot_strerror(INTERP, errno));
         }
 
         if (S_ISREG(info.st_mode))
@@ -155,20 +160,21 @@
 
     METHOD is_link(STRING *path) {
 #ifdef WIN32
-        /* I love win32 implementations */
+        /* I love win32. */
         RETURN(INTVAL 0);
 #else
         struct stat info;
+        char *cpath;
+        int error;
 
-        char *cpath = string_to_cstring(interp, path);
-        int error   = lstat(cpath, &info);
+        cpath = string_to_cstring(interp, path);
+        error = lstat(cpath, &info);
 
         string_cstring_free(cpath);
 
         if (error) {
-            char *errmsg = strerror(errno);
-            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_LIBRARY_ERROR, "%Ss",
+                    Parrot_strerror(INTERP, errno));
         }
 
         if (S_ISLNK(info.st_mode))
@@ -226,16 +232,14 @@
                 fclose(target);
             }
             else {
-                char *errmsg = strerror(errno);
-                Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                    errmsg);
+                Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_LIBRARY_ERROR, "%Ss",
+                        Parrot_strerror(INTERP, errno));
             }
             fclose(source);
         }
         else {
-            char *errmsg = strerror(errno);
-            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_LIBRARY_ERROR, "%Ss",
+                    Parrot_strerror(INTERP, errno));
         }
 #undef CHUNK_SIZE
     }
@@ -259,9 +263,8 @@
         string_cstring_free(cto);
 
         if (error) {
-            char *errmsg = strerror(errno);
-            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-                errmsg);
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_LIBRARY_ERROR, "%Ss",
+                    Parrot_strerror(INTERP, errno));
         }
     }
 }
Index: tools/dev/lib_deps.pl
===================================================================
--- tools/dev/lib_deps.pl	(revision 31174)
+++ tools/dev/lib_deps.pl	(working copy)
@@ -595,6 +595,7 @@
 strcpy      string.h
 strcspn     string.h
 strerror    string.h
+strerror_r  string.h
 strftime    time.h
 strlen      string.h
 strncat     string.h
Index: compilers/imcc/imclexer.c
===================================================================
--- compilers/imcc/imclexer.c	(revision 31174)
+++ compilers/imcc/imclexer.c	(working copy)
@@ -5908,7 +5908,7 @@
     FILE *file;
 
     if (!s || !(file = fopen(s, "r")))
-        IMCC_fataly(interp, EXCEPTION_PIO_ERROR, strerror(errno));
+        IMCC_fataly(interp, EXCEPTION_PIO_ERROR, "%Ss", Parrot_strerror(interp, errno));
 
     mem_sys_free(s);
     frame->s.file   = file_name;
Index: config/gen/platform/win32/stat.c
===================================================================
--- config/gen/platform/win32/stat.c	(revision 31174)
+++ config/gen/platform/win32/stat.c	(working copy)
@@ -86,9 +86,8 @@
         return status == 0;
 
     if (status == -1) {
-        const char *err = strerror(errno);
         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR,
-            "stat failed: %s", err);
+            "stat failed: %Ss", Parrot_strerror(interp, errno));
     }
 
     switch (thing) {
Index: config/gen/platform/win32/string.h
===================================================================
--- config/gen/platform/win32/string.h	(revision 31174)
+++ config/gen/platform/win32/string.h	(working copy)
@@ -12,6 +12,8 @@
 #  if _MSC_VER >= 1400
 #    define strdup _strdup
 #  endif
+/* This is only useful with msvc.  gcc/mingw can use strerror_r. */
+#  define strerror_r(errnum, buf, buflen) strerror_s((buf), (buflen), (errnum))
 #endif
 
 #endif /* PARROT_PLATFORM_WIN32_STRING_H_GUARD */
Index: config/gen/platform/platform_interface.h
===================================================================
--- config/gen/platform/platform_interface.h	(revision 31174)
+++ config/gen/platform/platform_interface.h	(working copy)
@@ -14,6 +14,7 @@
 ** I/O:
 */
 
+
 /*
 ** Math:
 */
@@ -130,6 +131,7 @@
 void Parrot_Exec_OS_Command(Interp*, struct parrot_string_t *);
 INTVAL Parrot_Run_OS_Command_Argv(Interp*, struct PMC *);
 void Parrot_Exec_OS_Command_Argv(Interp*, struct PMC *);
+struct parrot_string_t *Parrot_strerror(Interp* , INTVAL errnum);
 
 #endif /* PARROT_PLATFORM_INTERFACE_H_GUARD */
 
Index: config/gen/platform/generic/stat.c
===================================================================
--- config/gen/platform/generic/stat.c	(revision 31174)
+++ config/gen/platform/generic/stat.c	(working copy)
@@ -76,9 +76,8 @@
         return status == 0;
 
     if (status == -1) {
-        const char *err = strerror(errno);
         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXTERNAL_ERROR,
-            "stat failed: %s", err);
+            "stat failed: %Ss", Parrot_strerror(interp, errno));
     }
 
     switch (thing) {
Index: config/gen/platform/generic/strerror.c
===================================================================
--- config/gen/platform/generic/strerror.c	(revision 0)
+++ config/gen/platform/generic/strerror.c	(revision 0)
@@ -0,0 +1,82 @@
+/*
+ * $Id$
+ * Copyright (C) 2007-2008, The Perl Foundation.
+ */
+
+/*
+
+=head1 NAME
+
+config/gen/platform/generic/strerror.c
+
+=head1 DESCRIPTION
+
+This file contains Parrot_strerror, a platform-independent and reentrant
+wrapper for the various platform-specific strerror_* implementations.
+
+=head2 Function
+
+=over 4
+
+=item C<STRING *
+Parrot_strerror(PARROT_INTERP, INTVAL)>
+
+Wrap strerror_r, translating error numbers into error messages in Parrot
+STRING format.
+
+=cut
+
+*/
+
+#define ERRBUF_SIZE 512
+
+PARROT_API
+STRING *
+Parrot_strerror(PARROT_INTERP, INTVAL errnum)
+{
+    STRING *errstr;
+
+#if defined(WIN32) || \
+    (!defined(_GNU_SOURCE) && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L))
+
+    /* use POSIXy strerror_r (*nix) or strerror_s macro (msvc)*/
+    char errmsg[ERRBUF_SIZE];
+    int err_status;
+    err_status = strerror_r(errnum, errmsg, ERRBUF_SIZE);
+    /* Linux's POSIXy strerror_r returns -1 on error, others return an error code */
+    if (err_status == -1)
+        err_status = errnum;
+
+    if (err_status == 0 || err_status == ERANGE) {
+        errstr = string_printf(interp, "%s", errmsg);
+    }
+    else if (err_status == EINVAL){
+        errstr = string_printf(interp, "unknown error message (%d)", errnum);
+    }
+    else {
+        errstr = string_printf(interp,
+                "unknown error message from strerror_r (%d)", err_status);
+    }
+#else
+    /* GNU strerror_r DTRT for unknown error codes */
+    char buf[ERRBUF_SIZE];
+    char *errmsg = strerror_r(errnum, buf, ERRBUF_SIZE);
+    errstr = string_printf(interp, "%s", errmsg);
+#endif
+    return errstr;
+}
+
+/*
+
+=back
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */
Index: config/gen/platform.pm
===================================================================
--- config/gen/platform.pm	(revision 31174)
+++ config/gen/platform.pm	(working copy)
@@ -206,6 +206,7 @@
         math.c
         memalign.c
         signal.c
+        strerror.c
         itimer.c
         memexec.c
         exec.c

Reply via email to