Hi, On Tue, Nov 25, 2008 at 11:57:07AM +0100, Markus Hoenicka wrote: > > gmtime_r, readdir_r exists on both Linux and Cygwin platforms and > > according to man mages exists in FreeBSD as well: > > Yes, I've mentioned those as I do have access to them and positively > know they support the reentrant versions. I'm more concerned about the > systems that I don't run myself, like OSX, the other *BSDs, Solaris > and so on.
since all XSI compliant systems are required to provide thread- and reentrant-safe functions, those functions are fortunately available on the vast majority of systems. So if you compile with CPPFLAGS="-D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=500 -D_REENTRANT -D_THREAD_SAFE" you should get the XS-interface on all noted platforms, as far as I know. Of course, there are the occasional oddities here and there, as with all ``modern'' interfaces. For example, under Solaris, if you don't specify the above flags, you need to at least specify CPPFLAGS="-D_POSIX_PTHREAD_SEMANTICS" to get the standard-conforming versions of some functions, such as `strtok_r'. > > However readdir_r is less important because it is quite reasonable > > to load shared objects from single thread. > > > > Once again, it is reasonable, but we must not rely on users doing only > things that we assume as reasonable. Agreed. I use libdbi for a plugin to collectd[0]. Each plugin is called from a thread-pool, so using functions with static memory is an absolute no-go. Especially since it's not that big of a deal, really. In my experience, switching from `strerror' to `strerror_r' is the biggest deal, because it's often used in lots of places. > > Is there other points where non reenterable functions are used? > > To the best of my knowledge, not in libdbi. I didn't find any more thread-unsafe functions with a really quick check: [EMAIL PROTECTED]:~/libdbi $ egrep -riI '\<(asctime|ctermid|ctime|getgrgid|getgrnam|getlogin|getpwnam|getpwuid|gmtime|localtime|rand|readdir|srand|strerror|strtok|tmpnam|ttyname)\>' drivers/ [EMAIL PROTECTED]:~/libdbi $ Dunno if that's all thread-unsafe functions, but it's better than nothing ;) > This is a good excuse to make libdbi thread-safe :-) Please consider the attached patch. It's against what I considered to be the current CVS revision, but I haven't CVS for quite some time, so please forgive me if I'm a bit off ;) I did not remove that ugly `strtok == strtok_r' hack in src/dbi_result.c, but I added a warning to it. Is that really necessary? > > For the record I had seen in sqlite (not sqlite3) backend usage of > > strtok. So it should be thread unsafe. How does that make it thread-safe? Regards, -octo [0] <http://collectd.org/> -- Florian octo Forster Hacker in training GnuPG: 0x91523C3D http://verplant.org/
Index: configure.in
===================================================================
RCS file: /cvsroot/libdbi/libdbi/configure.in,v
retrieving revision 1.50
diff -p -u -w -r1.50 configure.in
--- configure.in 11 Nov 2008 23:52:03 -0000 1.50
+++ configure.in 25 Nov 2008 19:42:02 -0000
@@ -149,7 +149,7 @@ AC_DEFINE_UNQUOTED(DRIVER_EXT, "$shlib_e
AC_DEFINE_UNQUOTED(DLSYM_PREFIX, "$dlsym_prefix", [ Specifies a required prefix for symbol names of dynamically loaded modules ])
-AC_CHECK_FUNCS(strtoll)
+AC_CHECK_FUNCS(strtoll readdir_r gmtime_r)
AC_REPLACE_FUNCS(atoll timegm)
AC_CHECK_FUNCS(vasprintf)
AC_REPLACE_FUNCS(asprintf)
Index: src/dbi_main.c
===================================================================
RCS file: /cvsroot/libdbi/libdbi/src/dbi_main.c,v
retrieving revision 1.87
diff -p -u -w -r1.87 dbi_main.c
--- src/dbi_main.c 11 Nov 2008 23:51:42 -0000 1.87
+++ src/dbi_main.c 25 Nov 2008 19:42:03 -0000
@@ -170,7 +170,27 @@ int dbi_initialize_r(const char *driverd
return -1;
}
else {
- while ((driver_dirent = readdir(dir)) != NULL) {
+ struct dirent *buffer;
+ size_t buffer_size;
+ int status;
+
+ /* Allocate memory for readdir_r(3). */
+ buffer_size = sizeof (struct dirent)
+ + pathconf (effective_driverdir, _PC_NAME_MAX) + 1;
+ buffer = (struct dirent *) malloc (buffer_size);
+ if (buffer == NULL)
+ return -1;
+ memset (buffer, 0, buffer_size);
+
+ status = 0;
+ while (42) {
+ driver_dirent = NULL;
+ status = readdir_r (dir, buffer, &driver_dirent);
+ if (status != 0)
+ break;
+ if (driver_dirent == NULL)
+ break;
+
driver = NULL;
snprintf(fullpath, FILENAME_MAX, "%s%s%s", effective_driverdir, DBI_PATH_SEPARATOR, driver_dirent->d_name);
if ((stat(fullpath, &statbuf) == 0) && S_ISREG(statbuf.st_mode) && strrchr(driver_dirent->d_name, '.') && (!strcmp(strrchr(driver_dirent->d_name, '.'), DRIVER_EXT))) {
@@ -194,8 +214,12 @@ int dbi_initialize_r(const char *driverd
if (inst->dbi_verbosity) fprintf(stderr, "libdbi: Failed to load driver: %s\n", fullpath);
}
}
- }
+ } /* while (42) */
closedir(dir);
+ free (buffer);
+
+ if (status != 0)
+ return status;
}
return num_loaded;
Index: src/dbi_result.c
===================================================================
RCS file: /cvsroot/libdbi/libdbi/src/dbi_result.c,v
retrieving revision 1.48
diff -p -u -w -r1.48 dbi_result.c
--- src/dbi_result.c 19 Apr 2008 16:09:00 -0000 1.48
+++ src/dbi_result.c 25 Nov 2008 19:42:04 -0000
@@ -39,6 +39,7 @@
#include <dbi/dbi-dev.h>
#ifdef __MINGW32__
+#warning "Using the thread-unsafe strtok function!"
#define strtok_r(s1,s2,s3) strtok(s1,s2)
#endif
@@ -1442,7 +1450,7 @@ char *dbi_result_get_as_string_copy_idx(
char *ERROR = "ERROR";
char *newstring = NULL;
char *oldstring = NULL;
- struct tm *utctime;
+ struct tm utctime;
fieldidx--;
@@ -1530,8 +1538,8 @@ char *dbi_result_get_as_string_copy_idx(
case DBI_TYPE_BINARY:
break; /* return empty string, do not raise an error */
case DBI_TYPE_DATETIME:
- utctime = gmtime(&(RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_datetime));
- snprintf(newstring, 32, "%04d-%02d-%02d %02d:%02d:%02d", utctime->tm_year+1900, utctime->tm_mon+1, utctime->tm_mday, utctime->tm_hour, utctime->tm_min, utctime->tm_sec);
+ gmtime_r(&(RESULT->rows[RESULT->currowidx]->field_values[fieldidx].d_datetime), &utctime);
+ snprintf(newstring, 32, "%04d-%02d-%02d %02d:%02d:%02d", utctime.tm_year+1900, utctime.tm_mon+1, utctime.tm_mday, utctime.tm_hour, utctime.tm_min, utctime.tm_sec);
break;
default:
_error_handler(RESULT->conn, DBI_ERROR_BADTYPE);
Index: src/timegm.c
===================================================================
RCS file: /cvsroot/libdbi/libdbi/src/timegm.c,v
retrieving revision 1.1
diff -p -u -w -r1.1 timegm.c
--- src/timegm.c 13 Jan 2004 21:02:10 -0000 1.1
+++ src/timegm.c 25 Nov 2008 19:42:04 -0000
@@ -30,7 +30,7 @@
time_t timegm(struct tm *tm) {
time_t temp_ltime;
- struct tm *temp_gm;
+ struct tm temp_gm;
if (!tm) {
temp_ltime = 0;
@@ -39,9 +39,9 @@ time_t timegm(struct tm *tm) {
temp_ltime = mktime(tm);
}
- temp_gm = gmtime(&temp_ltime);
+ gmtime(&temp_ltime, &temp_gm);
- return (time_t)(temp_ltime + (temp_ltime - mktime(temp_gm)));
+ return (time_t)(temp_ltime + (temp_ltime - mktime(&temp_gm)));
}
#endif /* HAVE_TIMEGM */
signature.asc
Description: Digital signature
------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________ libdbi-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/libdbi-devel

