[BUG] fix calls to localtime()
localtime() was called with pointers to tv_sec, which is time_t on
some platforms and long on others. A problem was encountered on
Sparc64 under OpenBSD where tv_sec is long (64 bits) and time_t is
32 bits. Since this architecture is big-endian, it exhibited the
bug because localtime() always worked with the high part of the
value which is always zero. This problem was identified and debugged
by Thierry Fournier.
The correct solution is to pass the date by value and not by pointer,
through an intermediate function. The use of localtime_r() instead of
localtime() also made it possible to get rid of the first call to
localtime() since it does not need to allocate memory anymore.
diff --git a/src/haproxy.c b/src/haproxy.c
index cc2514b..1108ea9 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -392,12 +392,7 @@
global.rlimit_memmax = HAPROXY_MEMMAX;
#endif
- /* initialize the libc's localtime structures once for all so that we
- * won't be missing memory if we want to send alerts under OOM conditions.
- * Also, the Alert() and Warning() functions need <now> to be initialized.
- */
tv_now(&now);
- localtime((time_t *)&now.tv_sec);
start_date = now;
init_task();
diff --git a/src/log.c b/src/log.c
index 542dd0d..5566d1a 100644
--- a/src/log.c
+++ b/src/log.c
@@ -60,14 +60,14 @@
void Alert(const char *fmt, ...)
{
va_list argp;
- struct tm *tm;
+ struct tm tm;
if (!(global.mode & MODE_QUIET) || (global.mode & (MODE_VERBOSE | MODE_STARTING))) {
va_start(argp, fmt);
- tm = localtime((time_t *)&now.tv_sec);
+ get_localtime(now.tv_sec, &tm);
fprintf(stderr, "[ALERT] %03d/%02d%02d%02d (%d) : ",
- tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)getpid());
+ tm.tm_yday, tm.tm_hour, tm.tm_min, tm.tm_sec, (int)getpid());
vfprintf(stderr, fmt, argp);
fflush(stderr);
va_end(argp);
@@ -81,14 +81,14 @@
void Warning(const char *fmt, ...)
{
va_list argp;
- struct tm *tm;
+ struct tm tm;
if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
va_start(argp, fmt);
- tm = localtime((time_t *)&now.tv_sec);
+ get_localtime(now.tv_sec, &tm);
fprintf(stderr, "[WARNING] %03d/%02d%02d%02d (%d) : ",
- tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)getpid());
+ tm.tm_yday, tm.tm_hour, tm.tm_min, tm.tm_sec, (int)getpid());
vfprintf(stderr, fmt, argp);
fflush(stderr);
va_end(argp);
@@ -173,13 +173,15 @@
if (now.tv_sec != tvsec || dataptr == NULL) {
/* this string is rebuild only once a second */
- struct tm *tm = localtime((time_t *)&now.tv_sec);
+ struct tm tm;
+
tvsec = now.tv_sec;
+ get_localtime(tvsec, &tm);
hdr_len = snprintf(logmsg, sizeof(logmsg),
"<<<<>%s %2d %02d:%02d:%02d %s[%d]: ",
- monthname[tm->tm_mon],
- tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec,
+ monthname[tm.tm_mon],
+ tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
progname, pid);
/* WARNING: depending upon implementations, snprintf may return
* either -1 or the number of bytes that would be needed to store
@@ -275,7 +277,7 @@
struct proxy *prx_log;
int tolog;
char *svid;
- struct tm *tm;
+ struct tm tm;
if (s->cli_addr.ss_family == AF_INET)
inet_ntop(AF_INET,
@@ -286,7 +288,7 @@
(const void *)&((struct sockaddr_in6 *)(&s->cli_addr))->sin6_addr,
pn, sizeof(pn));
- tm = localtime((time_t *)&s->logs.tv_accept.tv_sec);
+ get_localtime(s->logs.tv_accept.tv_sec, &tm);
if (fe->logfac1 >= 0)
prx_log = fe;
@@ -312,8 +314,8 @@
(s->cli_addr.ss_family == AF_INET) ?
ntohs(((struct sockaddr_in *)&s->cli_addr)->sin_port) :
ntohs(((struct sockaddr_in6 *)&s->cli_addr)->sin6_port),
- tm->tm_mday, monthname[tm->tm_mon], tm->tm_year+1900,
- tm->tm_hour, tm->tm_min, tm->tm_sec, s->logs.tv_accept.tv_usec/1000,
+ tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
+ tm.tm_hour, tm.tm_min, tm.tm_sec, s->logs.tv_accept.tv_usec/1000,
fe->id, be->id, svid,
(s->logs.t_queue >= 0) ? s->logs.t_queue : -1,
(s->logs.t_connect >= 0) ? s->logs.t_connect - s->logs.t_queue : -1,
diff --git a/src/proto_http.c b/src/proto_http.c
index f9b51d8..f4ffae7 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -709,7 +709,7 @@
int tolog;
char *uri, *h;
char *svid;
- struct tm *tm;
+ struct tm tm;
static char tmpline[MAX_SYSLOG_LEN];
int hdr;
@@ -726,8 +726,7 @@
(const void *)&((struct sockaddr_in6 *)(&s->cli_addr))->sin6_addr,
pn, sizeof(pn));
- tm = localtime((time_t *)&s->logs.tv_accept.tv_sec);
-
+ get_localtime(s->logs.tv_accept.tv_sec, &tm);
/* FIXME: let's limit ourselves to frontend logging for now. */
tolog = fe->to_log;
@@ -785,8 +784,8 @@
(s->cli_addr.ss_family == AF_INET) ?
ntohs(((struct sockaddr_in *)&s->cli_addr)->sin_port) :
ntohs(((struct sockaddr_in6 *)&s->cli_addr)->sin6_port),
- tm->tm_mday, monthname[tm->tm_mon], tm->tm_year+1900,
- tm->tm_hour, tm->tm_min, tm->tm_sec, s->logs.tv_accept.tv_usec/1000,
+ tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
+ tm.tm_hour, tm.tm_min, tm.tm_sec, s->logs.tv_accept.tv_usec/1000,
fe->id, be->id, svid,
s->logs.t_request,
(s->logs.t_queue >= 0) ? s->logs.t_queue - s->logs.t_request : -1,