Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lxc
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
lxc
Commits
258e3e43
Commit
258e3e43
authored
Nov 28, 2016
by
Serge Hallyn
Committed by
GitHub
Nov 28, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1331 from brauner/2016-11-27/use_sec_nanosec_since_epoch
log: drop all timezone conversion functions
parents
1fbb7fae
d86c0d08
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
144 additions
and
62 deletions
+144
-62
log.c
src/lxc/log.c
+134
-60
log.h
src/lxc/log.h
+6
-2
utils.h
src/lxc/utils.h
+4
-0
No files found.
src/lxc/log.c
View file @
258e3e43
...
@@ -22,9 +22,12 @@
...
@@ -22,9 +22,12 @@
*/
*/
#define _GNU_SOURCE
#define _GNU_SOURCE
#define __STDC_FORMAT_MACROS
/* Required for PRIu64 to work. */
#include <assert.h>
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdio.h>
#include <errno.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <limits.h>
#include <unistd.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/types.h>
...
@@ -43,21 +46,11 @@
...
@@ -43,21 +46,11 @@
#include "caps.h"
#include "caps.h"
#include "utils.h"
#include "utils.h"
#define LXC_LOG_DATEFOMAT_SIZE 15
/* We're logging in seconds and nanoseconds. Assuming that the underlying
* datatype is currently at maximum a 64bit integer, we have a date string that
#ifndef HAVE_GETTID
* is of maximum length (2^64 - 1) * 2 = (21 + 21) = 42.
static
inline
pid_t
gettid
(
void
)
*/
{
#define LXC_LOG_TIME_SIZE ((__LXC_NUMSTRLEN) * 2)
#ifdef __NR_gettid
return
(
pid_t
)
syscall
(
SYS_gettid
);
#else
errno
=
ENOSYS
;
return
-
1
;
#endif
}
#else
extern
pid_t
gettid
(
void
);
#endif
int
lxc_log_fd
=
-
1
;
int
lxc_log_fd
=
-
1
;
static
int
syslog_enable
=
0
;
static
int
syslog_enable
=
0
;
...
@@ -148,14 +141,124 @@ static int log_append_stderr(const struct lxc_log_appender *appender,
...
@@ -148,14 +141,124 @@ static int log_append_stderr(const struct lxc_log_appender *appender,
}
}
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
int
lxc_unix_epoch_to_utc
(
char
*
buf
,
size_t
bufsize
,
const
struct
timespec
*
time
)
{
int64_t
epoch_to_days
,
z
,
era
,
doe
,
yoe
,
year
,
doy
,
mp
,
day
,
month
,
d_in_s
,
hours
,
h_in_s
,
minutes
,
seconds
;
char
nanosec
[
__LXC_NUMSTRLEN
];
int
ret
;
/* See https://howardhinnant.github.io/date_algorithms.html for an
* explanation of the algorithm used here.
*/
/* Convert Epoch in seconds to number of days. */
epoch_to_days
=
time
->
tv_sec
/
86400
;
/* Shift the Epoch from 1970-01-01 to 0000-03-01. */
z
=
epoch_to_days
+
719468
;
/* compute the era from the serial date by simply dividing by the number
* of days in an era (146097).
*/
era
=
(
z
>=
0
?
z
:
z
-
146096
)
/
146097
;
/* The day-of-era (doe) can then be found by subtracting the era number
* times the number of days per era, from the serial date.
*/
doe
=
(
z
-
era
*
146097
);
/* From the day-of-era (doe), the year-of-era (yoe, range [0, 399]) can
* be computed.
*/
yoe
=
(
doe
-
doe
/
1460
+
doe
/
36524
-
doe
/
146096
)
/
365
;
/* Given year-of-era, and era, one can now compute the year. */
year
=
(
yoe
)
+
era
*
400
;
/* Also the day-of-year, again with the year beginning on Mar. 1, can be
* computed from the day-of-era and year-of-era.
*/
doy
=
doe
-
(
365
*
yoe
+
yoe
/
4
-
yoe
/
100
);
/* Given day-of-year, find the month number. */
mp
=
(
5
*
doy
+
2
)
/
153
;
/* From day-of-year and month-of-year we can now easily compute
* day-of-month.
*/
day
=
doy
-
(
153
*
mp
+
2
)
/
5
+
1
;
/* Transform the month number from the [0, 11] / [Mar, Feb] system to
* the civil system: [1, 12] to find the correct month.
*/
month
=
mp
+
(
mp
<
10
?
3
:
-
9
);
/* Transform days in the epoch to seconds. */
d_in_s
=
epoch_to_days
*
86400
;
/* To find the current hour simply substract the Epoch_to_days from the
* total Epoch and divide by the number of seconds in an hour.
*/
hours
=
(
time
->
tv_sec
-
d_in_s
)
/
3600
;
/* Transform hours to seconds. */
h_in_s
=
hours
*
3600
;
/* Calculate minutes by substracting the seconds for all days in the
* epoch and for all hours in the epoch and divide by the number of
* minutes in an hour.
*/
minutes
=
(
time
->
tv_sec
-
d_in_s
-
h_in_s
)
/
60
;
/* Calculate the seconds by substracting the seconds for all days in the
* epoch, hours in the epoch and minutes in the epoch.
*/
seconds
=
(
time
->
tv_sec
-
d_in_s
-
h_in_s
-
(
minutes
*
60
));
/* Make string from nanoseconds. */
ret
=
snprintf
(
nanosec
,
__LXC_NUMSTRLEN
,
"%ld"
,
time
->
tv_nsec
);
if
(
ret
<
0
||
ret
>=
__LXC_NUMSTRLEN
)
return
-
1
;
/* Create final timestamp for the log and shorten nanoseconds to 3
* digit precision.
*/
ret
=
snprintf
(
buf
,
bufsize
,
"%"
PRId64
"%"
PRId64
"%"
PRId64
"%"
PRId64
"%"
PRId64
"%"
PRId64
".%.3s"
,
year
,
month
,
day
,
hours
,
minutes
,
seconds
,
nanosec
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
bufsize
)
return
-
1
;
return
0
;
}
/* This function needs to make extra sure that it is thread-safe. We had some
* problems with that before. This especially involves time-conversion
* functions. I don't want to find any localtime() or gmtime() functions or
* relatives in here. Not even localtime_r() or gmtime_r() or relatives. They
* all fiddle with global variables and locking in various libcs. They cause
* deadlocks when liblxc is used multi-threaded and no matter how smart you
* think you are, you __will__ cause trouble using them.
* (As a short example how this can cause trouble: LXD uses forkstart to fork
* off a new process that runs the container. At the same time the go runtime
* LXD relies on does its own multi-threading thing which we can't controll. The
* fork()ing + threading then seems to mess with the locking states in these
* time functions causing deadlocks.)
* The current solution is to be good old unix people and use the Epoch as our
* reference point and simply use the seconds and nanoseconds that have past
* since then. This relies on clock_gettime() which is explicitly marked MT-Safe
* with no restrictions! This way, anyone who is really strongly invested in
* getting the actual time the log entry was created, can just convert it for
* themselves. Our logging is mostly done for debugging purposes so don't try
* to make it pretty. Pretty might cost you thread-safety.
*/
static
int
log_append_logfile
(
const
struct
lxc_log_appender
*
appender
,
static
int
log_append_logfile
(
const
struct
lxc_log_appender
*
appender
,
struct
lxc_log_event
*
event
)
struct
lxc_log_event
*
event
)
{
{
char
date
[
LXC_LOG_DATEFOMAT_SIZE
]
=
"N/A"
;
char
buffer
[
LXC_LOG_BUFFER_SIZE
];
char
buffer
[
LXC_LOG_BUFFER_SIZE
];
struct
tm
newtime
;
char
date_time
[
LXC_LOG_TIME_SIZE
]
;
int
n
;
int
n
;
int
ms
=
0
;
int
fd_to_use
=
-
1
;
int
fd_to_use
=
-
1
;
#ifndef NO_LXC_CONF
#ifndef NO_LXC_CONF
...
@@ -169,48 +272,19 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
...
@@ -169,48 +272,19 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
if
(
fd_to_use
==
-
1
)
if
(
fd_to_use
==
-
1
)
return
0
;
return
0
;
/* localtime_r() can lead to deadlocks when LXC is used multithreaded
if
(
lxc_unix_epoch_to_utc
(
date_time
,
LXC_LOG_TIME_SIZE
,
&
event
->
timestamp
)
<
0
)
* because it calls __tzset() and __tzconvert() internally. The deadlock
return
0
;
* stems from an interaction between these functions and the functions
* in monitor.c and commands.{c,h}. Some of the latter functions will
n
=
snprintf
(
buffer
,
sizeof
(
buffer
),
* write to the log independent of the container thread that is
"%15s%s%s %s %-8s %s - %s:%s:%d - "
,
* currently running. Since the monitor fork()ed it seems to duplicate
log_prefix
,
* the mutex states of the time functions mentioned above.
log_vmname
?
" "
:
""
,
* As a short term fix, I suggest to simply disable receiving the time
log_vmname
?
log_vmname
:
""
,
* when these monitor.c or command.{c,h} functions are called. This
date_time
,
* should be ok, since the [lxc monitor] will only emit a few messages
lxc_log_priority_to_string
(
event
->
priority
),
* and thread-safety is currently more important than beautiful logs.
event
->
category
,
* The rest of the log stays the same as it was before.
event
->
locinfo
->
file
,
event
->
locinfo
->
func
,
*/
event
->
locinfo
->
line
);
if
(
getpid
()
==
gettid
())
{
if
(
!
localtime_r
(
&
event
->
timestamp
.
tv_sec
,
&
newtime
))
return
0
;
strftime
(
date
,
sizeof
(
date
),
"%Y%m%d%H%M%S"
,
&
newtime
);
ms
=
event
->
timestamp
.
tv_usec
/
1000
;
n
=
snprintf
(
buffer
,
sizeof
(
buffer
),
"%15s%s%s %14s.%03d %-8s %s - %s:%s:%d - "
,
log_prefix
,
log_vmname
?
" "
:
""
,
log_vmname
?
log_vmname
:
""
,
date
,
ms
,
lxc_log_priority_to_string
(
event
->
priority
),
event
->
category
,
event
->
locinfo
->
file
,
event
->
locinfo
->
func
,
event
->
locinfo
->
line
);
}
else
{
n
=
snprintf
(
buffer
,
sizeof
(
buffer
),
"%15s%s%s %-14s %3s %-8s %s - %s:%s:%d - "
,
log_prefix
,
log_vmname
?
" "
:
""
,
log_vmname
?
log_vmname
:
""
,
date
,
""
,
lxc_log_priority_to_string
(
event
->
priority
),
event
->
category
,
event
->
locinfo
->
file
,
event
->
locinfo
->
func
,
event
->
locinfo
->
line
);
}
if
(
n
<
0
)
if
(
n
<
0
)
return
n
;
return
n
;
...
...
src/lxc/log.h
View file @
258e3e43
...
@@ -34,6 +34,7 @@
...
@@ -34,6 +34,7 @@
#include <strings.h>
#include <strings.h>
#include <stdbool.h>
#include <stdbool.h>
#include <syslog.h>
#include <syslog.h>
#include <time.h>
#include "conf.h"
#include "conf.h"
...
@@ -83,7 +84,7 @@ struct lxc_log_locinfo {
...
@@ -83,7 +84,7 @@ struct lxc_log_locinfo {
struct
lxc_log_event
{
struct
lxc_log_event
{
const
char
*
category
;
const
char
*
category
;
int
priority
;
int
priority
;
struct
time
val
timestamp
;
struct
time
spec
timestamp
;
struct
lxc_log_locinfo
*
locinfo
;
struct
lxc_log_locinfo
*
locinfo
;
const
char
*
fmt
;
const
char
*
fmt
;
va_list
*
vap
;
va_list
*
vap
;
...
@@ -251,7 +252,10 @@ ATTR_UNUSED static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo, \
...
@@ -251,7 +252,10 @@ ATTR_UNUSED static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo, \
}; \
}; \
va_list va_ref; \
va_list va_ref; \
\
\
gettimeofday(&evt.timestamp, NULL); \
/* clock_gettime() is explicitly marked as MT-Safe \
* without restrictions. So let's use it for our \
* logging stamps. */
\
clock_gettime(CLOCK_REALTIME, &evt.timestamp); \
\
\
va_start(va_ref, format); \
va_start(va_ref, format); \
evt.vap = &va_ref; \
evt.vap = &va_ref; \
...
...
src/lxc/utils.h
View file @
258e3e43
...
@@ -35,6 +35,10 @@
...
@@ -35,6 +35,10 @@
#include "initutils.h"
#include "initutils.h"
/* Useful macros */
/* Maximum number for 64 bit integer is a string with 21 digits: 2^64 - 1 = 21 */
#define __LXC_NUMSTRLEN 21
/* returns 1 on success, 0 if there were any failures */
/* returns 1 on success, 0 if there were any failures */
extern
int
lxc_rmdir_onedev
(
char
*
path
,
const
char
*
exclude
);
extern
int
lxc_rmdir_onedev
(
char
*
path
,
const
char
*
exclude
);
extern
int
get_u16
(
unsigned
short
*
val
,
const
char
*
arg
,
int
base
);
extern
int
get_u16
(
unsigned
short
*
val
,
const
char
*
arg
,
int
base
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment