Skip to content

Commit 8ebc756

Browse files
committed
fix cldeadlock crashes
- dangling clnt->thd: worker now clears sqlthd->clnt / clnt->thd (under gbl_sql_lock / clnt->sql_lk) before signal_clnt_as_done; skipped on nested replay; watchdog long-running-clnt scan reads clnt->thd once - SEGV in newsql_write_postponed_evbuffer: only set postponed_write if the postponed row was actually saved; NULL-check before sending - abort sending startgen with rqid 0: keep rqid on the lock-desired restart path when keep_rqid, and don't resend commit logic on an ended session
1 parent c83b6af commit 8ebc756

6 files changed

Lines changed: 39 additions & 8 deletions

File tree

db/osqlsqlthr.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,12 @@ static int osql_sock_start_int(struct sqlclntstate *clnt, int type,
246246
rc = clnt_check_bdb_lock_desired(clnt);
247247
if (rc) {
248248
logmsg(LOGMSG_ERROR, "recover_deadlock returned %d\n", rc);
249-
rc = osql_end(clnt);
250-
if (rc) {
251-
logmsg(LOGMSG_ERROR, "%s failed to end osql %d\n", __func__, rc);
249+
/* keep_rqid: session is being restarted, don't zero rqid */
250+
if (!keep_rqid) {
251+
rc = osql_end(clnt);
252+
if (rc) {
253+
logmsg(LOGMSG_ERROR, "%s failed to end osql %d\n", __func__, rc);
254+
}
252255
}
253256
return SQLITE_BUSY;
254257
}
@@ -1211,7 +1214,8 @@ int osql_sock_commit(struct sqlclntstate *clnt, int type, enum trans_clntcomm si
12111214
int keep_session = !is_final || (get_cnonce(clnt, &snap) == 0);
12121215

12131216
rc = osql_sock_restart(clnt, 1, keep_session, is_final);
1214-
if (sock_restart_retryable_rcode(rc) && !clnt->is_coordinator) {
1217+
/* don't resend on an ended session (rqid 0) */
1218+
if (sock_restart_retryable_rcode(rc) && osql->rqid && !clnt->is_coordinator) {
12151219
if (gbl_master_swing_sock_restart_sleep) {
12161220
sleep(gbl_master_swing_sock_restart_sleep);
12171221
}

db/reqlog.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1992,7 +1992,9 @@ void reqlog_long_running_clnt(struct sqlclntstate *clnt)
19921992
{
19931993
int have_fingerprint = 0;
19941994
char fp[FINGERPRINTSZ] = {0};
1995-
if (clnt->done || !clnt->thd || !clnt->sql || !clnt->thd->logger) return;
1995+
/* single read: worker clears clnt->thd concurrently */
1996+
struct sqlthdstate *thd = clnt->thd;
1997+
if (clnt->done || !thd || !clnt->sql || !thd->logger) return;
19961998

19971999
if (can_consume(clnt) == 1) {
19982000
return; /* Do not log consumers */

db/sqlglue.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10268,7 +10268,11 @@ int recover_deadlock_flags(bdb_state_type *bdb_state, struct sqlclntstate *clnt,
1026810268
clnt->recover_deadlock_thd = pthread_self();
1026910269
comdb2_cheapstack_char_array(clnt->recover_deadlock_stack, RECOVER_DEADLOCK_MAX_STACK);
1027010270
#endif
10271-
recover_deadlock_sc_cleanup(clnt->thd->sqlthd);
10271+
/* use TLS thd (as recover_deadlock_flags_int does): clnt->thd may
10272+
* already be cleared when called from the post-done flush path */
10273+
struct sql_thread *sqlthd = pthread_getspecific(query_info_key);
10274+
if (sqlthd)
10275+
recover_deadlock_sc_cleanup(sqlthd);
1027210276
assert(bdb_lockref() == 0);
1027310277
} else {
1027410278
assert(bdb_lockref() > 0);

db/sqlinterfaces.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4081,8 +4081,8 @@ static int run_stmt(struct sqlthdstate *thd, struct sqlclntstate *clnt,
40814081
if (rc)
40824082
return rc;
40834083
} else {
4084-
postponed_write = 1;
4085-
send_row(clnt, stmt, row_id, 1, NULL);
4084+
/* only claim a postponed row if the save succeeded */
4085+
postponed_write = (send_row(clnt, stmt, row_id, 1, NULL) == 0);
40864086
}
40874087

40884088
rowcount++;
@@ -4858,6 +4858,21 @@ static int can_execute_sql_query_now(
48584858
return 1;
48594859
}
48604860

4861+
/* clear before signal: signal hands clnt back to the event thread.
4862+
* nested replay call: outer frame still owns thd */
4863+
static void clnt_detach_thd(struct sqlclntstate *clnt, struct sql_thread *sqlthd)
4864+
{
4865+
if (clnt->osql.in_replay_nested)
4866+
return;
4867+
Pthread_mutex_lock(&gbl_sql_lock);
4868+
sqlthd->clnt = NULL;
4869+
Pthread_mutex_unlock(&gbl_sql_lock);
4870+
/* sql_lk: watchdog reads clnt->thd under it */
4871+
Pthread_mutex_lock(&clnt->sql_lk);
4872+
clnt->thd = NULL; /* thd is about to go away */
4873+
Pthread_mutex_unlock(&clnt->sql_lk);
4874+
}
4875+
48614876
void sqlengine_work_appsock(struct sqlthdstate *thd, struct sqlclntstate *clnt)
48624877
{
48634878
struct sql_thread *sqlthd = thd->sqlthd;
@@ -4908,6 +4923,7 @@ void sqlengine_work_appsock(struct sqlthdstate *thd, struct sqlclntstate *clnt)
49084923
clnt->osql.timings.query_finished = osql_log_time();
49094924
osql_log_time_done(clnt);
49104925
clnt_change_state(clnt, CONNECTION_IDLE);
4926+
clnt_detach_thd(clnt, sqlthd);
49114927
signal_clnt_as_done(clnt);
49124928
return;
49134929
}
@@ -4960,6 +4976,7 @@ void sqlengine_work_appsock(struct sqlthdstate *thd, struct sqlclntstate *clnt)
49604976
osql_log_time_done(clnt);
49614977
clnt_change_state(clnt, CONNECTION_IDLE);
49624978
debug_close_clnt(clnt);
4979+
clnt_detach_thd(clnt, sqlthd);
49634980
signal_clnt_as_done(clnt);
49644981

49654982
thrman_setid(thrman_self(), "[done]");

db/sqloffload.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,9 @@ int osql_clean_sqlclntstate(struct sqlclntstate *clnt)
641641
abort();
642642
}
643643

644+
int in_replay_nested = osql->in_replay_nested; /* call-stack state, not txn state */
644645
bzero(osql, sizeof(*osql));
646+
osql->in_replay_nested = in_replay_nested;
645647
listc_init(&osql->shadtbls, offsetof(struct shad_tbl, linkv));
646648

647649
sql_set_sqlengine_state(clnt, __FILE__, __LINE__, SQLENG_NORMAL_PROCESS);

plugins/newsql/newsql.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,8 @@ static int newsql_save_postponed_row(struct sqlclntstate *clnt,
616616
static int newsql_send_postponed_row(struct sqlclntstate *clnt)
617617
{
618618
struct newsql_appdata *appdata = clnt->appdata;
619+
if (appdata->postponed == NULL)
620+
return -1;
619621
return appdata->write_postponed(clnt);
620622
}
621623

0 commit comments

Comments
 (0)