Skip to content

Commit cdcf71e

Browse files
author
Tor Didriksen
committed
Bug#14649493 ASSERTION FAILURE IN __GCOV_FLUSH IN _DB_SUICIDE_ (DBUG_SUICIDE)
Grab THR_LOCK_gcov before calling __gcov_flush() to avoid multiple parallel calls.
1 parent 686cac3 commit cdcf71e

File tree

4 files changed

+64
-13
lines changed

4 files changed

+64
-13
lines changed

dbug/dbug.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,14 @@ static void DbugVfprintf(FILE *stream, const char* format, va_list args);
356356

357357
#include <my_pthread.h>
358358
static pthread_mutex_t THR_LOCK_dbug;
359+
360+
/**
361+
A mutex protecting flushing of gcov data, see _db_flush_gcov_().
362+
We don't re-use THR_LOCK_dbug, because that would disallow:
363+
DBUG_LOCK_FILE; ..... DBUG_SUICIDE(); .... DBUG_UNLOCK_FILE;
364+
*/
365+
static pthread_mutex_t THR_LOCK_gcov;
366+
359367
/**
360368
Lock, to protect @c init_settings.
361369
For performance reasons,
@@ -378,6 +386,7 @@ static CODE_STATE *code_state(void)
378386
{
379387
init_done=TRUE;
380388
pthread_mutex_init(&THR_LOCK_dbug, NULL);
389+
pthread_mutex_init(&THR_LOCK_gcov, NULL);
381390
my_rwlock_init(&THR_LOCK_init_settings, NULL);
382391
memset(&init_settings, 0, sizeof(init_settings));
383392
init_settings.out_file=stderr;
@@ -2383,6 +2392,16 @@ void _db_flush_()
23832392
extern void __gcov_flush();
23842393
#endif
23852394

2395+
void _db_flush_gcov_()
2396+
{
2397+
#ifdef HAVE_GCOV
2398+
// Gcov will assert() if we try to flush in parallel.
2399+
pthread_mutex_lock(&THR_LOCK_gcov);
2400+
__gcov_flush();
2401+
pthread_mutex_unlock(&THR_LOCK_gcov);
2402+
#endif
2403+
}
2404+
23862405
void _db_suicide_()
23872406
{
23882407
int retval;
@@ -2392,7 +2411,7 @@ void _db_suicide_()
23922411
#ifdef HAVE_GCOV
23932412
fprintf(stderr, "Flushing gcov data\n");
23942413
fflush(stderr);
2395-
__gcov_flush();
2414+
_db_flush_gcov_();
23962415
#endif
23972416

23982417
fprintf(stderr, "SIGKILL myself\n");

include/my_dbug.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ extern const char* _db_get_func_(void);
133133
#define DBUG_SUICIDE() DBUG_ABORT()
134134
#else
135135
extern void _db_suicide_();
136+
extern void _db_flush_gcov_();
136137
#define DBUG_SUICIDE() (_db_flush_(), _db_suicide_())
137138
#endif
138139

mysys/stacktrace.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -418,18 +418,7 @@ void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
418418
/* Produce a core for the thread */
419419
void my_write_core(int sig)
420420
{
421-
#ifdef HAVE_gcov
422-
extern void __gcov_flush(void);
423-
#endif
424421
signal(sig, SIG_DFL);
425-
#ifdef HAVE_gcov
426-
/*
427-
For GCOV build, crashing will prevent the writing of code coverage
428-
information from this process, causing gcov output to be incomplete.
429-
So we force the writing of coverage information here before terminating.
430-
*/
431-
__gcov_flush();
432-
#endif
433422
pthread_kill(pthread_self(), sig);
434423
#if defined(P_MYID) && !defined(SCO)
435424
/* On Solaris, the above kill is not enough */

unittest/gunit/dbug-t.cc

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -17,9 +17,16 @@
1717
#include "my_config.h"
1818
#include <gtest/gtest.h>
1919

20+
#include "thread_utils.h"
21+
2022
#include "my_global.h"
2123
#include "my_dbug.h"
2224

25+
using thread::Notification;
26+
using thread::Thread;
27+
28+
namespace {
29+
2330
#if defined(DBUG_OFF)
2431
TEST(DebugTest, NoSuicide)
2532
{
@@ -32,3 +39,38 @@ TEST(DebugDeathTest, Suicide)
3239
EXPECT_DEATH_IF_SUPPORTED(DBUG_SUICIDE(), "");
3340
}
3441
#endif
42+
43+
44+
#if !defined(DBUG_OFF) && !defined(__WIN__)
45+
class DbugGcovThread : public Thread
46+
{
47+
public:
48+
DbugGcovThread(Notification *start_notification)
49+
: m_start_notification(start_notification)
50+
{}
51+
52+
virtual void run()
53+
{
54+
m_start_notification->notify();
55+
_db_flush_gcov_();
56+
}
57+
58+
private:
59+
Notification *m_start_notification;
60+
};
61+
62+
63+
TEST(DebugFlushGcov, FlushGcovParallel)
64+
{
65+
Notification start_notification;
66+
DbugGcovThread debug_thread(&start_notification);
67+
debug_thread.start();
68+
69+
// Wait for the other thread to start, then flush in parallel.
70+
start_notification.wait_for_notification();
71+
_db_flush_gcov_();
72+
debug_thread.join();
73+
}
74+
#endif
75+
76+
}

0 commit comments

Comments
 (0)