Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
1043c806
Commit
1043c806
authored
Mar 28, 2012
by
antirez
Browse files
Merge branch 'watchdog' into unstable
parents
0fefb5bb
d174eed5
Changes
7
Hide whitespace changes
Inline
Side-by-side
src/bio.c
View file @
1043c806
...
@@ -108,9 +108,18 @@ void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) {
...
@@ -108,9 +108,18 @@ void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) {
void
*
bioProcessBackgroundJobs
(
void
*
arg
)
{
void
*
bioProcessBackgroundJobs
(
void
*
arg
)
{
struct
bio_job
*
job
;
struct
bio_job
*
job
;
unsigned
long
type
=
(
unsigned
long
)
arg
;
unsigned
long
type
=
(
unsigned
long
)
arg
;
sigset_t
sigset
;
pthread_detach
(
pthread_self
());
pthread_detach
(
pthread_self
());
pthread_mutex_lock
(
&
bio_mutex
[
type
]);
pthread_mutex_lock
(
&
bio_mutex
[
type
]);
/* Block SIGALRM so we are sure that only the main thread will
* receive the watchdog signal. */
sigemptyset
(
&
sigset
);
sigaddset
(
&
sigset
,
SIGALRM
);
if
(
pthread_sigmask
(
SIG_BLOCK
,
&
sigset
,
NULL
))
redisLog
(
REDIS_WARNING
,
"Warning: can't mask SIGALRM in bio.c thread: %s"
,
strerror
(
errno
));
while
(
1
)
{
while
(
1
)
{
listNode
*
ln
;
listNode
*
ln
;
...
...
src/config.c
View file @
1043c806
...
@@ -627,6 +627,12 @@ void configSetCommand(redisClient *c) {
...
@@ -627,6 +627,12 @@ void configSetCommand(redisClient *c) {
}
else
if
(
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
"repl-timeout"
))
{
}
else
if
(
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
"repl-timeout"
))
{
if
(
getLongLongFromObject
(
o
,
&
ll
)
==
REDIS_ERR
||
ll
<=
0
)
goto
badfmt
;
if
(
getLongLongFromObject
(
o
,
&
ll
)
==
REDIS_ERR
||
ll
<=
0
)
goto
badfmt
;
server
.
repl_timeout
=
ll
;
server
.
repl_timeout
=
ll
;
}
else
if
(
!
strcasecmp
(
c
->
argv
[
2
]
->
ptr
,
"watchdog-period"
))
{
if
(
getLongLongFromObject
(
o
,
&
ll
)
==
REDIS_ERR
||
ll
<
0
)
goto
badfmt
;
if
(
ll
)
enableWatchdog
(
ll
);
else
disableWatchdog
();
}
else
{
}
else
{
addReplyErrorFormat
(
c
,
"Unsupported CONFIG parameter: %s"
,
addReplyErrorFormat
(
c
,
"Unsupported CONFIG parameter: %s"
,
(
char
*
)
c
->
argv
[
2
]
->
ptr
);
(
char
*
)
c
->
argv
[
2
]
->
ptr
);
...
@@ -715,6 +721,7 @@ void configGetCommand(redisClient *c) {
...
@@ -715,6 +721,7 @@ void configGetCommand(redisClient *c) {
config_get_numerical_field
(
"repl-ping-slave-period"
,
server
.
repl_ping_slave_period
);
config_get_numerical_field
(
"repl-ping-slave-period"
,
server
.
repl_ping_slave_period
);
config_get_numerical_field
(
"repl-timeout"
,
server
.
repl_timeout
);
config_get_numerical_field
(
"repl-timeout"
,
server
.
repl_timeout
);
config_get_numerical_field
(
"maxclients"
,
server
.
maxclients
);
config_get_numerical_field
(
"maxclients"
,
server
.
maxclients
);
config_get_numerical_field
(
"watchdog-period"
,
server
.
watchdog_period
);
/* Bool (yes/no) values */
/* Bool (yes/no) values */
config_get_bool_field
(
"no-appendfsync-on-rewrite"
,
config_get_bool_field
(
"no-appendfsync-on-rewrite"
,
...
...
src/debug.c
View file @
1043c806
...
@@ -559,10 +559,11 @@ void logRegisters(ucontext_t *uc) {
...
@@ -559,10 +559,11 @@ void logRegisters(ucontext_t *uc) {
}
}
/* Logs the stack trace using the backtrace() call. */
/* Logs the stack trace using the backtrace() call. */
void
log
StackTrace
(
ucontext_t
*
uc
)
{
sds
get
StackTrace
(
ucontext_t
*
uc
)
{
void
*
trace
[
100
];
void
*
trace
[
100
];
int
i
,
trace_size
=
0
;
int
i
,
trace_size
=
0
;
char
**
messages
=
NULL
;
char
**
messages
=
NULL
;
sds
st
=
sdsempty
();
/* Generate the stack trace */
/* Generate the stack trace */
trace_size
=
backtrace
(
trace
,
100
);
trace_size
=
backtrace
(
trace
,
100
);
...
@@ -572,9 +573,12 @@ void logStackTrace(ucontext_t *uc) {
...
@@ -572,9 +573,12 @@ void logStackTrace(ucontext_t *uc) {
trace
[
1
]
=
getMcontextEip
(
uc
);
trace
[
1
]
=
getMcontextEip
(
uc
);
}
}
messages
=
backtrace_symbols
(
trace
,
trace_size
);
messages
=
backtrace_symbols
(
trace
,
trace_size
);
redisLog
(
REDIS_WARNING
,
"--- STACK TRACE"
);
for
(
i
=
1
;
i
<
trace_size
;
++
i
)
{
for
(
i
=
1
;
i
<
trace_size
;
++
i
)
st
=
sdscat
(
st
,
messages
[
i
]);
redisLog
(
REDIS_WARNING
,
"%s"
,
messages
[
i
]);
st
=
sdscatlen
(
st
,
"
\n
"
,
1
);
}
zlibc_free
(
messages
);
return
st
;
}
}
/* Log information about the "current" client, that is, the client that is
/* Log information about the "current" client, that is, the client that is
...
@@ -617,7 +621,7 @@ void logCurrentClient(void) {
...
@@ -617,7 +621,7 @@ void logCurrentClient(void) {
void
sigsegvHandler
(
int
sig
,
siginfo_t
*
info
,
void
*
secret
)
{
void
sigsegvHandler
(
int
sig
,
siginfo_t
*
info
,
void
*
secret
)
{
ucontext_t
*
uc
=
(
ucontext_t
*
)
secret
;
ucontext_t
*
uc
=
(
ucontext_t
*
)
secret
;
sds
infostring
,
clients
;
sds
infostring
,
clients
,
st
;
struct
sigaction
act
;
struct
sigaction
act
;
REDIS_NOTUSED
(
info
);
REDIS_NOTUSED
(
info
);
...
@@ -629,7 +633,9 @@ void sigsegvHandler(int sig, siginfo_t *info, void *secret) {
...
@@ -629,7 +633,9 @@ void sigsegvHandler(int sig, siginfo_t *info, void *secret) {
server
.
assert_file
,
server
.
assert_line
);
server
.
assert_file
,
server
.
assert_line
);
/* Log the stack trace */
/* Log the stack trace */
logStackTrace
(
uc
);
st
=
getStackTrace
(
uc
);
redisLog
(
REDIS_WARNING
,
"--- STACK TRACE
\n
%s"
,
st
);
sdsfree
(
st
);
/* Log INFO and CLIENT LIST */
/* Log INFO and CLIENT LIST */
redisLog
(
REDIS_WARNING
,
"--- INFO OUTPUT"
);
redisLog
(
REDIS_WARNING
,
"--- INFO OUTPUT"
);
...
@@ -661,11 +667,87 @@ void sigsegvHandler(int sig, siginfo_t *info, void *secret) {
...
@@ -661,11 +667,87 @@ void sigsegvHandler(int sig, siginfo_t *info, void *secret) {
/* Make sure we exit with the right signal at the end. So for instance
/* Make sure we exit with the right signal at the end. So for instance
* the core will be dumped if enabled. */
* the core will be dumped if enabled. */
sigemptyset
(
&
act
.
sa_mask
);
sigemptyset
(
&
act
.
sa_mask
);
/* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction
* is used. Otherwise, sa_handler is used */
act
.
sa_flags
=
SA_NODEFER
|
SA_ONSTACK
|
SA_RESETHAND
;
act
.
sa_flags
=
SA_NODEFER
|
SA_ONSTACK
|
SA_RESETHAND
;
act
.
sa_handler
=
SIG_DFL
;
act
.
sa_handler
=
SIG_DFL
;
sigaction
(
sig
,
&
act
,
NULL
);
sigaction
(
sig
,
&
act
,
NULL
);
kill
(
getpid
(),
sig
);
kill
(
getpid
(),
sig
);
}
}
#endif
/* HAVE_BACKTRACE */
#endif
/* HAVE_BACKTRACE */
/* =========================== Software Watchdog ============================ */
#include <sys/time.h>
void
watchdogSignalHandler
(
int
sig
,
siginfo_t
*
info
,
void
*
secret
)
{
ucontext_t
*
uc
=
(
ucontext_t
*
)
secret
;
REDIS_NOTUSED
(
info
);
REDIS_NOTUSED
(
sig
);
sds
st
,
log
;
time_t
now
=
time
(
NULL
);
char
date
[
128
];
FILE
*
fp
;
fp
=
(
server
.
logfile
==
NULL
)
?
stdout
:
fopen
(
server
.
logfile
,
"a"
);
if
(
fp
==
NULL
)
return
;
strftime
(
date
,
sizeof
(
date
),
"%d %b %H:%M:%S"
,
localtime
(
&
now
));
log
=
sdscatprintf
(
sdsempty
(),
"
\n
--- WATCHDOG TIMER EXPIRED (%s) ---
\n
"
,
date
);
#ifdef HAVE_BACKTRACE
st
=
getStackTrace
(
uc
);
#else
st
=
sdsnew
(
"Sorry: no support for backtrace().
\n
"
);
#endif
log
=
sdscatsds
(
log
,
st
);
log
=
sdscat
(
log
,
"------
\n\n
"
);
fprintf
(
fp
,
"%s"
,
log
);
if
(
server
.
logfile
)
fclose
(
fp
);
sdsfree
(
st
);
sdsfree
(
log
);
}
/* Schedule a SIGALRM delivery after the specified period in milliseconds.
* If a timer is already scheduled, this function will re-schedule it to the
* specified time. If period is 0 the current timer is disabled. */
void
watchdogScheduleSignal
(
int
period
)
{
struct
itimerval
it
;
/* Will stop the timer if period is 0. */
it
.
it_value
.
tv_sec
=
period
/
1000
;
it
.
it_value
.
tv_usec
=
(
period
%
1000
)
*
1000
;
/* Don't automatically restart. */
it
.
it_interval
.
tv_sec
=
0
;
it
.
it_interval
.
tv_usec
=
0
;
setitimer
(
ITIMER_REAL
,
&
it
,
NULL
);
}
/* Enable the software watchdong with the specified period in milliseconds. */
void
enableWatchdog
(
int
period
)
{
if
(
server
.
watchdog_period
==
0
)
{
struct
sigaction
act
;
/* Watchdog was actually disabled, so we have to setup the signal
* handler. */
sigemptyset
(
&
act
.
sa_mask
);
act
.
sa_flags
=
SA_NODEFER
|
SA_ONSTACK
|
SA_SIGINFO
;
act
.
sa_sigaction
=
watchdogSignalHandler
;
sigaction
(
SIGALRM
,
&
act
,
NULL
);
}
if
(
period
<
200
)
period
=
200
;
/* We don't accept periods < 200 ms. */
watchdogScheduleSignal
(
period
);
/* Adjust the current timer. */
server
.
watchdog_period
=
period
;
}
/* Disable the software watchdog. */
void
disableWatchdog
(
void
)
{
struct
sigaction
act
;
if
(
server
.
watchdog_period
==
0
)
return
;
/* Already disabled. */
watchdogScheduleSignal
(
0
);
/* Stop the current timer. */
/* Set the signal handler to SIG_IGN, this will also remove pending
* signals from the queue. */
sigemptyset
(
&
act
.
sa_mask
);
act
.
sa_flags
=
0
;
act
.
sa_handler
=
SIG_IGN
;
sigaction
(
SIGALRM
,
&
act
,
NULL
);
server
.
watchdog_period
=
0
;
}
src/redis.c
View file @
1043c806
...
@@ -726,6 +726,10 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
...
@@ -726,6 +726,10 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
REDIS_NOTUSED
(
id
);
REDIS_NOTUSED
(
id
);
REDIS_NOTUSED
(
clientData
);
REDIS_NOTUSED
(
clientData
);
/* Software watchdog: deliver the SIGALRM that will reach the signal
* handler if we don't return here fast enough. */
if
(
server
.
watchdog_period
)
watchdogScheduleSignal
(
server
.
watchdog_period
);
/* We take a cached value of the unix time in the global state because
/* We take a cached value of the unix time in the global state because
* with virtual memory and aging there is to store the current time
* with virtual memory and aging there is to store the current time
* in objects at every object access, and accuracy is not needed.
* in objects at every object access, and accuracy is not needed.
...
@@ -1084,11 +1088,12 @@ void initServerConfig() {
...
@@ -1084,11 +1088,12 @@ void initServerConfig() {
server
.
slowlog_log_slower_than
=
REDIS_SLOWLOG_LOG_SLOWER_THAN
;
server
.
slowlog_log_slower_than
=
REDIS_SLOWLOG_LOG_SLOWER_THAN
;
server
.
slowlog_max_len
=
REDIS_SLOWLOG_MAX_LEN
;
server
.
slowlog_max_len
=
REDIS_SLOWLOG_MAX_LEN
;
/*
Assert
*/
/*
Debugging
*/
server
.
assert_failed
=
"<no assertion failed>"
;
server
.
assert_failed
=
"<no assertion failed>"
;
server
.
assert_file
=
"<no file>"
;
server
.
assert_file
=
"<no file>"
;
server
.
assert_line
=
0
;
server
.
assert_line
=
0
;
server
.
bug_report_start
=
0
;
server
.
bug_report_start
=
0
;
server
.
watchdog_period
=
0
;
}
}
/* This function will try to raise the max number of open files accordingly to
/* This function will try to raise the max number of open files accordingly to
...
...
src/redis.h
View file @
1043c806
...
@@ -722,6 +722,7 @@ struct redisServer {
...
@@ -722,6 +722,7 @@ struct redisServer {
char
*
assert_file
;
char
*
assert_file
;
int
assert_line
;
int
assert_line
;
int
bug_report_start
;
/* True if bug report header was already logged. */
int
bug_report_start
;
/* True if bug report header was already logged. */
int
watchdog_period
;
/* Software watchdog period in ms. 0 = off */
};
};
typedef
struct
pubsubPattern
{
typedef
struct
pubsubPattern
{
...
@@ -1255,4 +1256,7 @@ void bugReportStart(void);
...
@@ -1255,4 +1256,7 @@ void bugReportStart(void);
void
redisLogObjectDebugInfo
(
robj
*
o
);
void
redisLogObjectDebugInfo
(
robj
*
o
);
void
sigsegvHandler
(
int
sig
,
siginfo_t
*
info
,
void
*
secret
);
void
sigsegvHandler
(
int
sig
,
siginfo_t
*
info
,
void
*
secret
);
sds
genRedisInfoString
(
char
*
section
);
sds
genRedisInfoString
(
char
*
section
);
void
enableWatchdog
(
int
period
);
void
disableWatchdog
(
void
);
void
watchdogScheduleSignal
(
int
period
);
#endif
#endif
src/zmalloc.c
View file @
1043c806
...
@@ -30,6 +30,15 @@
...
@@ -30,6 +30,15 @@
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
/* This function provide us access to the original libc free(). This is useful
* for instance to free results obtained by backtrace_symbols(). We need
* to define this function before including zmalloc.h that may shadow the
* free implementation if we use jemalloc or another non standard allocator. */
void
zlibc_free
(
void
*
ptr
)
{
free
(
ptr
);
}
#include <string.h>
#include <string.h>
#include <pthread.h>
#include <pthread.h>
#include "config.h"
#include "config.h"
...
...
src/zmalloc.h
View file @
1043c806
...
@@ -75,6 +75,7 @@ size_t zmalloc_used_memory(void);
...
@@ -75,6 +75,7 @@ size_t zmalloc_used_memory(void);
void
zmalloc_enable_thread_safeness
(
void
);
void
zmalloc_enable_thread_safeness
(
void
);
float
zmalloc_get_fragmentation_ratio
(
void
);
float
zmalloc_get_fragmentation_ratio
(
void
);
size_t
zmalloc_get_rss
(
void
);
size_t
zmalloc_get_rss
(
void
);
void
zlibc_free
(
void
*
ptr
);
#ifndef HAVE_MALLOC_SIZE
#ifndef HAVE_MALLOC_SIZE
size_t
zmalloc_size
(
void
*
ptr
);
size_t
zmalloc_size
(
void
*
ptr
);
...
...
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