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