Skip to content

Commit 5cec834

Browse files
committed
MDEV-29896: mariadb-backup --backup --incremental --throttle=... hangs
io_watching_thread(): Declare as a detachable thread, similar to log_copying_thread(). stop_backup_threads(): Wait for both log_copying_thread and io_watching_thread to clear their flags. Expect log_sys.mutex to be held by the caller. xtrabackup_backup_func(): Initialize log_copying_stop before creating io_watching_thread. This prevents a race condition where io_watching_thread() could wait on the condition variable before it had been fully initialized. This race condition would cause a hang in the GNU libc implementation of pthread_cond_destroy() at the end of stop_backup_threads(). This race condition was introduced in commit 38fd7b7 (MDEV-21452).
1 parent 5eb545e commit 5cec834

File tree

2 files changed

+27
-25
lines changed

2 files changed

+27
-25
lines changed

extra/mariabackup/xtrabackup.cc

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ struct xb_filter_entry_t{
190190
lsn_t checkpoint_lsn_start;
191191
lsn_t checkpoint_no_start;
192192
static lsn_t log_copy_scanned_lsn;
193+
/** whether log_copying_thread() is active; protected by log_sys.mutex */
193194
static bool log_copying_running;
194195

195196
int xtrabackup_parallel;
@@ -3092,16 +3093,18 @@ static void log_copying_thread()
30923093
my_thread_end();
30933094
}
30943095

3096+
/** whether io_watching_thread() is active; protected by log_sys.mutex */
30953097
static bool have_io_watching_thread;
3096-
static pthread_t io_watching_thread_id;
30973098

30983099
/* io throttle watching (rough) */
3099-
static void *io_watching_thread(void*)
3100+
static void io_watching_thread()
31003101
{
3102+
my_thread_init();
31013103
/* currently, for --backup only */
3102-
ut_a(xtrabackup_backup);
3104+
ut_ad(xtrabackup_backup);
31033105

31043106
mysql_mutex_lock(&log_sys.mutex);
3107+
ut_ad(have_io_watching_thread);
31053108

31063109
while (log_copying_running && !metadata_to_lsn)
31073110
{
@@ -3114,9 +3117,10 @@ static void *io_watching_thread(void*)
31143117

31153118
/* stop io throttle */
31163119
xtrabackup_throttle= 0;
3120+
have_io_watching_thread= false;
31173121
mysql_cond_broadcast(&wait_throttle);
31183122
mysql_mutex_unlock(&log_sys.mutex);
3119-
return nullptr;
3123+
my_thread_end();
31203124
}
31213125

31223126
#ifndef DBUG_OFF
@@ -4377,27 +4381,29 @@ static ulong xb_set_max_open_files(rlim_t max_file_limit)
43774381
# define xb_set_max_open_files(x) 0UL
43784382
#endif
43794383

4380-
static void stop_backup_threads(bool running)
4384+
static void stop_backup_threads()
43814385
{
4382-
if (running)
4386+
mysql_cond_broadcast(&log_copying_stop);
4387+
4388+
if (log_copying_running || have_io_watching_thread)
43834389
{
4390+
mysql_mutex_unlock(&log_sys.mutex);
43844391
fputs("mariabackup: Stopping log copying thread", stderr);
43854392
fflush(stderr);
4386-
while (log_copying_running)
4393+
mysql_mutex_lock(&log_sys.mutex);
4394+
while (log_copying_running || have_io_watching_thread)
43874395
{
4396+
mysql_cond_broadcast(&log_copying_stop);
4397+
mysql_mutex_unlock(&log_sys.mutex);
43884398
putc('.', stderr);
43894399
fflush(stderr);
43904400
std::this_thread::sleep_for(std::chrono::milliseconds(200));
4401+
mysql_mutex_lock(&log_sys.mutex);
43914402
}
43924403
putc('\n', stderr);
4393-
mysql_cond_destroy(&log_copying_stop);
43944404
}
43954405

4396-
if (have_io_watching_thread)
4397-
{
4398-
pthread_join(io_watching_thread_id, nullptr);
4399-
mysql_cond_destroy(&wait_throttle);
4400-
}
4406+
mysql_cond_destroy(&log_copying_stop);
44014407
}
44024408

44034409
/** Implement the core of --backup
@@ -4427,11 +4433,7 @@ static bool xtrabackup_backup_low()
44274433
msg("Error: recv_find_max_checkpoint() failed.");
44284434
}
44294435

4430-
mysql_cond_broadcast(&log_copying_stop);
4431-
const bool running= log_copying_running;
4432-
mysql_mutex_unlock(&log_sys.mutex);
4433-
stop_backup_threads(running);
4434-
mysql_mutex_lock(&log_sys.mutex);
4436+
stop_backup_threads();
44354437
}
44364438

44374439
if (metadata_to_lsn && xtrabackup_copy_logfile(true)) {
@@ -4532,9 +4534,8 @@ static bool xtrabackup_backup_func()
45324534
if (log_copying_running) {
45334535
mysql_mutex_lock(&log_sys.mutex);
45344536
metadata_to_lsn = 1;
4535-
mysql_cond_broadcast(&log_copying_stop);
4537+
stop_backup_threads();
45364538
mysql_mutex_unlock(&log_sys.mutex);
4537-
stop_backup_threads(true);
45384539
}
45394540

45404541
log_file_op = NULL;
@@ -4695,13 +4696,15 @@ static bool xtrabackup_backup_func()
46954696

46964697
aligned_free(log_hdr_buf);
46974698
log_copying_running = true;
4699+
4700+
mysql_cond_init(0, &log_copying_stop, nullptr);
4701+
46984702
/* start io throttle */
4699-
if(xtrabackup_throttle) {
4703+
if (xtrabackup_throttle) {
47004704
io_ticket = xtrabackup_throttle;
47014705
have_io_watching_thread = true;
47024706
mysql_cond_init(0, &wait_throttle, nullptr);
4703-
mysql_thread_create(0, &io_watching_thread_id, nullptr,
4704-
io_watching_thread, nullptr);
4707+
std::thread(io_watching_thread).detach();
47054708
}
47064709

47074710
/* Populate fil_system with tablespaces to copy */
@@ -4729,7 +4732,6 @@ static bool xtrabackup_backup_func()
47294732

47304733
DBUG_MARIABACKUP_EVENT("before_innodb_log_copy_thread_started", {});
47314734

4732-
mysql_cond_init(0, &log_copying_stop, nullptr);
47334735
std::thread(log_copying_thread).detach();
47344736

47354737
/* FLUSH CHANGED_PAGE_BITMAPS call */

mysql-test/suite/mariabackup/incremental_backup.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ INSERT INTO t VALUES(1);
3434

3535
echo # Create full backup , modify table, then create incremental/differential backup;
3636
--disable_result_log
37-
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$basedir;
37+
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$basedir --throttle=1000;
3838
--enable_result_log
3939
BEGIN;
4040
INSERT INTO t VALUES(0);

0 commit comments

Comments
 (0)