Skip to content

Commit

Permalink
bio: fix doFastMemoryTest.
Browse files Browse the repository at this point in the history
If one thread got SIGSEGV, function sigsegvHandler() would be triggered,
it would call bioKillThreads(). But call pthread_cancel() to cancel itself
would make it block. Also note that if SIGSEGV is caught by bio thread, it
should kill the main thread in order to give a positive report.
  • Loading branch information
trevor211 authored and oranagra committed Sep 16, 2020
1 parent 810e28a commit 8b70cb0
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 3 deletions.
3 changes: 2 additions & 1 deletion src/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,11 @@ void bioKillThreads(void) {
int err, j;

for (j = 0; j < BIO_NUM_OPS; j++) {
if (bio_threads[j] == pthread_self()) continue;
if (bio_threads[j] && pthread_cancel(bio_threads[j]) == 0) {
if ((err = pthread_join(bio_threads[j],NULL)) != 0) {
serverLog(LL_WARNING,
"Bio thread for job type #%d can be joined: %s",
"Bio thread for job type #%d can not be joined: %s",
j, strerror(err));
} else {
serverLog(LL_WARNING,
Expand Down
22 changes: 21 additions & 1 deletion src/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -1565,12 +1565,32 @@ int memtest_test_linux_anonymous_maps(void) {
}
#endif

static void killMainThread(void) {
int err;
if (pthread_self() != server.main_thread_id && pthread_cancel(server.main_thread_id) == 0) {
if ((err = pthread_join(server.main_thread_id,NULL)) != 0) {
serverLog(LL_WARNING, "main thread can not be joined: %s", strerror(err));
} else {
serverLog(LL_WARNING, "main thread terminated");
}
}
}

/* Kill the running threads (other than current) in an unclean way. This function
* should be used only when it's critical to stop the threads for some reason.
* Currently Redis does this only on crash (for instance on SIGSEGV) in order
* to perform a fast memory check without other threads messing with memory. */
static void killThreads(void) {
killMainThread();
bioKillThreads();
}

void doFastMemoryTest(void) {
#if defined(HAVE_PROC_MAPS)
if (server.memcheck_enabled) {
/* Test memory */
serverLogRaw(LL_WARNING|LL_RAW, "\n------ FAST MEMORY TEST ------\n");
bioKillThreads();
killThreads();
if (memtest_test_linux_anonymous_maps()) {
serverLogRaw(LL_WARNING|LL_RAW,
"!!! MEMORY ERROR DETECTED! Check your memory ASAP !!!\n");
Expand Down
2 changes: 1 addition & 1 deletion src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -2879,6 +2879,7 @@ void initServer(void) {
server.aof_state = server.aof_enabled ? AOF_ON : AOF_OFF;
server.hz = server.config_hz;
server.pid = getpid();
server.main_thread_id = pthread_self();
server.current_client = NULL;
server.fixed_time_expire = 0;
server.clients = listCreate();
Expand Down Expand Up @@ -5174,7 +5175,6 @@ int iAmMaster(void) {
(server.cluster_enabled && nodeIsMaster(server.cluster->myself)));
}


int main(int argc, char **argv) {
struct timeval tv;
int j;
Expand Down
1 change: 1 addition & 0 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,7 @@ struct clusterState;
struct redisServer {
/* General */
pid_t pid; /* Main process pid. */
pthread_t main_thread_id; /* Main thread id */
char *configfile; /* Absolute config file path, or NULL */
char *executable; /* Absolute executable file path. */
char **exec_argv; /* Executable argv vector (copy). */
Expand Down

0 comments on commit 8b70cb0

Please sign in to comment.