Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions lib/Base_Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,9 +347,19 @@ void Base_Thread::tune_timeout_for_myds_needs_pause(DS * myds) {
template<typename T, typename DS>
void Base_Thread::tune_timeout_for_session_needs_pause(DS * myds) {
T* thr = static_cast<T*>(this);
if (thr->mypolls.poll_timeout==0 || (myds->sess->pause_until - curtime < thr->mypolls.poll_timeout) ) {
thr->mypolls.poll_timeout= myds->sess->pause_until - curtime;
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 7, "Session=%p , poll_timeout=%u , pause_until=%llu , curtime=%llu\n", myds->sess, thr->mypolls.poll_timeout, myds->sess->pause_until, curtime);

// Only adjust poll_timeout if the pause is still in the future. If pause_until
// is stale (already <= curtime), computing (pause_until - curtime) as unsigned
// would underflow to ~1.8e19 and corrupt poll_timeout, making poll() fall back
// to the default timeout (~2s) and stalling the worker thread. The stale-pause
// case is handled by check_timing_out_session (AfterPoll) and the handler-entry
// pause checks, so doing nothing here is correct.
if (myds->sess->pause_until > curtime) {
if (thr->mypolls.poll_timeout == 0 || (myds->sess->pause_until - curtime < thr->mypolls.poll_timeout)) {
thr->mypolls.poll_timeout = myds->sess->pause_until - curtime;
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 7, "Session=%p , poll_timeout=%u , pause_until=%llu , curtime=%llu\n", myds->sess, thr->mypolls.poll_timeout,
myds->sess->pause_until, curtime);
}
}
}
Comment on lines +357 to 364

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The logic for handling expired pauses should be enabled, and a unit mismatch in the timeout calculation needs to be addressed:

  1. Expired Pauses: The commented-out else block should be active. If pause_until <= curtime, the session is ready for processing. By not updating poll_timeout to a small value (like 1ms), the thread may block for the default timeout (2000ms), causing the freeze described in the PR summary.
  2. Unit Mismatch: pause_until - curtime is in microseconds, but poll_timeout is compared downstream against a millisecond value (2000 ms). If poll_timeout is set to microseconds, the comparison timeout < 2000 will fail for any pause longer than 2ms, causing the tuning to be ignored. The difference should be converted to milliseconds.
	if (myds->sess->pause_until > curtime) {
		// Future pause: align poll_timeout to the pause expiration.
		// Convert microseconds to milliseconds (ceiling division)
		unsigned int timeout_ms = (myds->sess->pause_until - curtime + 999) / 1000;
		if (thr->mypolls.poll_timeout == 0 || timeout_ms < (unsigned int)thr->mypolls.poll_timeout) {
			thr->mypolls.poll_timeout = timeout_ms;
			proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 7, "Session=%p , poll_timeout=%u , pause_until=%llu , curtime=%llu\n", myds->sess, thr->mypolls.poll_timeout, 
				myds->sess->pause_until, curtime);
		}
	} else {
		// pause_until > 0 (caller checked) but <= curtime: pause has already expired.
		// Wake poll() immediately rather than computing (pause_until - curtime)
		if (thr->mypolls.poll_timeout == 0 || thr->mypolls.poll_timeout > 1) {
			thr->mypolls.poll_timeout = 1;
		}
	}


Expand Down
3 changes: 2 additions & 1 deletion lib/MySQL_Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3013,6 +3013,7 @@ bool MySQL_Session::handler_again___status_CONNECTING_SERVER(int *_rc) {

st=previous_status.top();
previous_status.pop();
pause_until = 0;
NEXT_IMMEDIATE_NEW(st);
}
assert(st==status);
Expand All @@ -3039,7 +3040,7 @@ bool MySQL_Session::handler_again___status_CONNECTING_SERVER(int *_rc) {
st=previous_status.top();
previous_status.pop();
myds->wait_until=0;

pause_until = 0;
if (handle_session_track_capabilities() == false) {
previous_status.push(st);
pause_until = thread->curtime + mysql_thread___connect_retries_delay * 1000;
Expand Down
2 changes: 2 additions & 0 deletions lib/PgSQL_Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1634,6 +1634,7 @@ bool PgSQL_Session::handler_again___status_CONNECTING_SERVER(int* _rc) {
if (mybe->server_myds->myconn->async_state_machine == ASYNC_IDLE) {
st = previous_status.top();
previous_status.pop();
pause_until = 0;
NEXT_IMMEDIATE_NEW(st);
}
assert(st == status);
Expand Down Expand Up @@ -1671,6 +1672,7 @@ bool PgSQL_Session::handler_again___status_CONNECTING_SERVER(int* _rc) {
st = previous_status.top();
previous_status.pop();
myds->wait_until = 0;
pause_until = 0;
if (session_fast_forward) {
// we have a successful connection and session_fast_forward enabled
// set DSS=STATE_SLEEP or it will believe it have to use MARIADB client library
Expand Down
Loading