diff options
author | Riza Sulistyo <riza@teluu.com> | 2016-10-13 04:32:29 +0000 |
---|---|---|
committer | Riza Sulistyo <riza@teluu.com> | 2016-10-13 04:32:29 +0000 |
commit | 4412f8cdfdab2c140f70e10e0932a30c5091373b (patch) | |
tree | 0eb2b2fc7b9d1bffe8a2ac031180e187e1be0666 | |
parent | 94144542bbf37dd74b10865a4125ddaf9c119068 (diff) |
Re #1945 (misc): Use localtime_r() instead of localtime() (if available) since localtime() is not thread safe.
This fixes a data race in pj_time_decode() which is called from multiple threads.
Thanks to Kal (b17 c0de) for the patch.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5458 74dad513-b988-da41-8d7b-12977e46ad98
-rwxr-xr-x | aconfigure | 6 | ||||
-rw-r--r-- | aconfigure.ac | 3 | ||||
-rw-r--r-- | pjlib/include/pj/compat/os_auto.h.in | 3 | ||||
-rw-r--r-- | pjlib/include/pj/compat/os_darwinos.h | 2 | ||||
-rw-r--r-- | pjlib/include/pj/compat/os_linux.h | 2 | ||||
-rw-r--r-- | pjlib/src/pj/os_time_common.c | 25 |
6 files changed, 31 insertions, 10 deletions
@@ -5414,6 +5414,12 @@ if test "x$ac_cv_header_net_if_h" = xyes; then : fi +ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r" +if test "x$ac_cv_func_localtime_r" = xyes; then : + $as_echo "#define PJ_HAS_LOCALTIME_R 1" >>confdefs.h + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Setting PJ_OS_NAME to $target" >&5 $as_echo "Setting PJ_OS_NAME to $target" >&6; } cat >>confdefs.h <<_ACEOF diff --git a/aconfigure.ac b/aconfigure.ac index df9e1ae2..387a37ce 100644 --- a/aconfigure.ac +++ b/aconfigure.ac @@ -265,6 +265,9 @@ AC_CHECK_HEADER(net/if.h,[AC_DEFINE(PJ_HAS_NET_IF_H,1)],[], # include <sys/socket.h> #endif ]) + +AC_CHECK_FUNC(localtime_r,[AC_DEFINE(PJ_HAS_LOCALTIME_R,1)]) + AC_MSG_RESULT([Setting PJ_OS_NAME to $target]) AC_DEFINE_UNQUOTED(PJ_OS_NAME,["$target"]) diff --git a/pjlib/include/pj/compat/os_auto.h.in b/pjlib/include/pj/compat/os_auto.h.in index 7eb89562..70018ba6 100644 --- a/pjlib/include/pj/compat/os_auto.h.in +++ b/pjlib/include/pj/compat/os_auto.h.in @@ -166,6 +166,9 @@ # define PJ_OS_HAS_CHECK_STACK 0 #endif +/* Is localtime_r() available? */ +#undef PJ_HAS_LOCALTIME_R + /* Unicode? */ #undef PJ_NATIVE_STRING_IS_UNICODE diff --git a/pjlib/include/pj/compat/os_darwinos.h b/pjlib/include/pj/compat/os_darwinos.h index 8cccd425..98435a8b 100644 --- a/pjlib/include/pj/compat/os_darwinos.h +++ b/pjlib/include/pj/compat/os_darwinos.h @@ -55,6 +55,8 @@ #define PJ_HAS_WINSOCK_H 0 #define PJ_HAS_WINSOCK2_H 0 +#define PJ_HAS_LOCALTIME_R 1 + /* Is errno a good way to retrieve OS errors? */ #define PJ_HAS_ERRNO_VAR 1 diff --git a/pjlib/include/pj/compat/os_linux.h b/pjlib/include/pj/compat/os_linux.h index 40840e25..c33f2c19 100644 --- a/pjlib/include/pj/compat/os_linux.h +++ b/pjlib/include/pj/compat/os_linux.h @@ -55,6 +55,8 @@ #define PJ_HAS_WINSOCK_H 0 #define PJ_HAS_WINSOCK2_H 0 +#define PJ_HAS_LOCALTIME_R 1 + #define PJ_SOCK_HAS_INET_ATON 1 /* Set 1 if native sockaddr_in has sin_len member. diff --git a/pjlib/src/pj/os_time_common.c b/pjlib/src/pj/os_time_common.c index da4440d1..f14fa961 100644 --- a/pjlib/src/pj/os_time_common.c +++ b/pjlib/src/pj/os_time_common.c @@ -28,19 +28,24 @@ PJ_DEF(pj_status_t) pj_time_decode(const pj_time_val *tv, pj_parsed_time *pt) { - struct tm *local_time; + struct tm local_time; PJ_CHECK_STACK(); - local_time = localtime((time_t*)&tv->sec); - - pt->year = local_time->tm_year+1900; - pt->mon = local_time->tm_mon; - pt->day = local_time->tm_mday; - pt->hour = local_time->tm_hour; - pt->min = local_time->tm_min; - pt->sec = local_time->tm_sec; - pt->wday = local_time->tm_wday; +#if defined(PJ_HAS_LOCALTIME_R) && PJ_HAS_LOCALTIME_R != 0 + localtime_r((time_t*)&tv->sec, &local_time); +#else + /* localtime() is NOT thread-safe. */ + local_time = *localtime((time_t*)&tv->sec); +#endif + + pt->year = local_time.tm_year+1900; + pt->mon = local_time.tm_mon; + pt->day = local_time.tm_mday; + pt->hour = local_time.tm_hour; + pt->min = local_time.tm_min; + pt->sec = local_time.tm_sec; + pt->wday = local_time.tm_wday; pt->msec = tv->msec; return PJ_SUCCESS; |