From 313c1a8d7aa63a93058a2ec7d14573ab48c53faa Mon Sep 17 00:00:00 2001 From: Lammert Bies Date: Thu, 29 Dec 2016 01:11:44 +0100 Subject: [PATCH] httplib_localtime_r thread safe --- Makefile | 9 +-- include/libhttp.h | 1 + ...ce_localtime_s.c => httplib_localtime_r.c} | 50 ++++++++++------ src/httplib_log_access.c | 6 +- src/httplib_print_dir_entry.c | 5 +- src/wince_localtime.c | 60 ------------------- 6 files changed, 38 insertions(+), 93 deletions(-) rename src/{wince_localtime_s.c => httplib_localtime_r.c} (65%) delete mode 100644 src/wince_localtime.c diff --git a/Makefile b/Makefile index d3b79f57..5033d6db 100644 --- a/Makefile +++ b/Makefile @@ -407,8 +407,7 @@ OBJLIST = \ ${OBJDIR}httplib_pthread_setspecific${OBJEXT} \ ${OBJDIR}wince_gmtime${OBJEXT} \ ${OBJDIR}wince_gmtime_s${OBJEXT} \ - ${OBJDIR}wince_localtime${OBJEXT} \ - ${OBJDIR}wince_localtime_s${OBJEXT} \ + ${OBJDIR}httplib_localtime_r${OBJEXT} \ ${OBJDIR}wince_rename${OBJEXT} \ ${OBJDIR}wince_stat${OBJEXT} \ ${OBJDIR}wince_strftime${OBJEXT} \ @@ -1447,11 +1446,7 @@ ${OBJDIR}wince_gmtime_s${OBJEXT} : ${SRCDIR}wince_gmtime_s.c \ ${SRCDIR}httplib_utils.h \ ${INCDIR}libhttp.h -${OBJDIR}wince_localtime${OBJEXT} : ${SRCDIR}wince_localtime.c \ - ${SRCDIR}httplib_main.h \ - ${INCDIR}libhttp.h - -${OBJDIR}wince_localtime_s${OBJEXT} : ${SRCDIR}wince_localtime_s.c \ +${OBJDIR}httplib_localtime_r${OBJEXT} : ${SRCDIR}httplib_localtime_r.c \ ${SRCDIR}httplib_main.h \ ${SRCDIR}httplib_utils.h \ ${INCDIR}libhttp.h diff --git a/include/libhttp.h b/include/libhttp.h index 6523f2c9..ba78cde4 100644 --- a/include/libhttp.h +++ b/include/libhttp.h @@ -922,6 +922,7 @@ LIBHTTP_API const char * httplib_get_option( const struct httplib_context *ctx, LIBHTTP_API uint64_t httplib_get_random( void ); LIBHTTP_API void * httplib_get_user_connection_data( const struct httplib_connection *conn ); LIBHTTP_API int httplib_kill( pid_t pid, int sig_num ); +LIBHTTP_API struct tm * httplib_localtime_r( const time_t *clock, struct tm *result ); LIBHTTP_API int httplib_mkdir( const char *path, int mode ); LIBHTTP_API DIR * httplib_opendir( const char *name ); LIBHTTP_API int httplib_poll( struct pollfd *pfd, unsigned int nfds, int timeout ); diff --git a/src/wince_localtime_s.c b/src/httplib_localtime_r.c similarity index 65% rename from src/wince_localtime_s.c rename to src/httplib_localtime_r.c index eb194bf1..d5eeb953 100644 --- a/src/wince_localtime_s.c +++ b/src/httplib_localtime_r.c @@ -34,15 +34,19 @@ const int XX_httplib_days_per_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +#endif /* _WIN32_WCE */ + /* - * struct tm *localtime_s( const time_t *ptime, struct tm *ptm ); + * struct tm *httplib_localtime_r( const time_t *clock, struct tm *result ); * * The function localtime_s() returns a converted time to tm structure. This * function is not available on all operating systems and this version offers * a subsitute for use on Windows CE. */ -struct tm *localtime_s( const time_t *ptime, struct tm *ptm ) { +struct tm *httplib_localtime_r( const time_t *clock, struct tm *result ) { + +#if defined(_WIN32_WCE) int a; int doy; @@ -51,30 +55,38 @@ struct tm *localtime_s( const time_t *ptime, struct tm *ptm ) { SYSTEMTIME st; TIME_ZONE_INFORMATION tzinfo; - if ( ptime == NULL || ptm == NULL ) return NULL; + if ( clock == NULL || result == NULL ) return NULL; - *(int64_t *)&ft = ((int64_t)*ptime) * RATE_DIFF + EPOCH_DIFF; + *(int64_t *)&ft = ((int64_t)*clock) * RATE_DIFF + EPOCH_DIFF; FileTimeToLocalFileTime( & ft, & lft ); FileTimeToSystemTime( & lft, & st ); - ptm->tm_year = st.wYear - 1900; - ptm->tm_mon = st.wMonth - 1; - ptm->tm_wday = st.wDayOfWeek; - ptm->tm_mday = st.wDay; - ptm->tm_hour = st.wHour; - ptm->tm_min = st.wMinute; - ptm->tm_sec = st.wSecond; - ptm->tm_isdst = (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT) ? 1 : 0; + result->tm_year = st.wYear - 1900; + result->tm_mon = st.wMonth - 1; + result->tm_wday = st.wDayOfWeek; + result->tm_mday = st.wDay; + result->tm_hour = st.wHour; + result->tm_min = st.wMinute; + result->tm_sec = st.wSecond; + result->tm_isdst = (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT) ? 1 : 0; - doy = ptm->tm_mday; - for (a=0; atm_mon; a++) doy += days_per_month[a]; - if ( ptm->tm_mon >= 2 && LEAP_YEAR( ptm->tm_year+1900 ) ) doy++; + doy = result->tm_mday; + for (a=0; atm_mon; a++) doy += days_per_month[a]; + if ( result->tm_mon >= 2 && LEAP_YEAR( result->tm_year+1900 ) ) doy++; - ptm->tm_yday = doy; + result->tm_yday = doy; - return ptm; + return result; -} /* localtime_s */ +#elif defined(_WIN32) -#endif /* defined(_WIN32_WCE) */ + return localtime_s( clock, result ); + +#else + + return localtime_r( clock, result ); + +#endif + +} /* httplib_localtime_r */ diff --git a/src/httplib_log_access.c b/src/httplib_log_access.c index 612abeb0..610f4b1d 100644 --- a/src/httplib_log_access.c +++ b/src/httplib_log_access.c @@ -43,7 +43,7 @@ void XX_httplib_log_access( const struct httplib_connection *conn ) { struct file fi; char date[64]; char src_addr[IP_ADDR_STR_LEN]; - struct tm *tm; + struct tm tmm; const char *referer; const char *user_agent; char buf[4096]; @@ -63,9 +63,7 @@ void XX_httplib_log_access( const struct httplib_connection *conn ) { if ( fi.fp == NULL && conn->ctx->callbacks.log_access == NULL ) return; - tm = localtime( & conn->conn_birth_time ); - - if ( tm != NULL ) strftime( date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm ); + if ( httplib_localtime_r( &conn->conn_birth_time, &tmm ) != NULL ) strftime( date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", &tmm ); else { httplib_strlcpy( date, "01/Jan/1970:00:00:00 +0000", sizeof(date) ); date[sizeof(date) - 1] = '\0'; diff --git a/src/httplib_print_dir_entry.c b/src/httplib_print_dir_entry.c index c11443d4..5146e728 100644 --- a/src/httplib_print_dir_entry.c +++ b/src/httplib_print_dir_entry.c @@ -33,7 +33,7 @@ void XX_httplib_print_dir_entry( struct de *de ) { char size[64]; char mod[64]; char href[PATH_MAX * 3 /* worst case */]; - struct tm *tm; + struct tm tmm; if ( de->file.is_directory ) XX_httplib_snprintf( de->conn, NULL, size, sizeof(size), "%s", "[DIRECTORY]" ); else { @@ -53,8 +53,7 @@ void XX_httplib_print_dir_entry( struct de *de ) { * So, string truncation checks are not required here. */ - tm = localtime( &de->file.last_modified ); - if ( tm != NULL ) strftime( mod, sizeof(mod), "%d-%b-%Y %H:%M", tm ); + if ( httplib_localtime_r( &de->file.last_modified, &tmm ) != NULL ) strftime( mod, sizeof(mod), "%d-%b-%Y %H:%M", &tmm ); else { httplib_strlcpy( mod, "01-Jan-1970 00:00", sizeof(mod) ); diff --git a/src/wince_localtime.c b/src/wince_localtime.c deleted file mode 100644 index 17e8ad3f..00000000 --- a/src/wince_localtime.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2016 Lammert Bies - * Copyright (c) 2013-2016 the Civetweb developers - * Copyright (c) 2004-2013 Sergey Lyubka - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * ============ - * Release: 2.0 - */ - -#include "httplib_main.h" - -#if defined(_WIN32_WCE) - -struct tm XX_httplib_tm_array[MAX_WORKER_THREADS]; -volatile int XX_httplib_tm_index = 0; - -/* - * struct tm *localtime( const time_t *ptime ); - * - * The time conversion function localtime() is not available on all platforms. - * This implementation provides an equivalent function which can be used on - * platforms where the native system libraries have no support for localtime(). - * The function is thread safe by using an array with multiple entries to - * store the outcome of the function. Please note however that the number of - * entries in the table is equal to the normal number of threads started by - * LibHTTP, but this still may lead to overwriting results in border cases - * where the application creates additional threads which also use calls to - * this localtime implementation(). - * - * The implementation should therefore use thread local storage in the future. - */ - -struct tm *localtime( const time_t *ptime ) { - - int i; - - i = XX_httplib_atomic_inc( & XX_httplib_tm_index ) % MAX_WORKER_THREADS; - return localtime_s( ptime, XX_httplib_tm_array + i ); - -} /* localtime */ - -#endif /* defined(_WIN32_WCE) */