bio: fix doFastMemoryTest.

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.

(cherry picked from commit 8b70cb0ef8)
This commit is contained in:
WuYunlong 2020-09-15 13:06:47 +08:00 committed by Oran Agra
parent 7601ed344c
commit 5d9332266d
4 changed files with 25 additions and 3 deletions

View File

@ -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,

View File

@ -1512,6 +1512,26 @@ 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();
}
/* Scans the (assumed) x86 code starting at addr, for a max of `len`
* bytes, searching for E8 (callq) opcodes, and dumping the symbols
* and the call offset if they appear to be valid. */
@ -1589,7 +1609,7 @@ void sigsegvHandler(int sig, siginfo_t *info, void *secret) {
#if defined(HAVE_PROC_MAPS)
/* 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");

View File

@ -2814,6 +2814,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();
@ -5091,7 +5092,6 @@ int iAmMaster(void) {
(server.cluster_enabled && nodeIsMaster(server.cluster->myself)));
}
int main(int argc, char **argv) {
struct timeval tv;
int j;

View File

@ -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). */