Stop using dbcancel as the nogvl unblock function - #607
emailrhoads wants to merge 2 commits into
Conversation
MRI calls the UBF on any pending interrupt (including SIGCHLD on main), which aborted in-flight batches and made Result#each return []. Client :timeout still uses dbsetinterrupt. Co-authored-by: Cursor <cursoragent@cursor.com>
|
@andyundso any thoughts on this idea? |
|
@emailrhoads I am trying to grasp the consequence of this change. If you have some time and maybe dev environment running, can you add the following test to client = new_connection
assert_client_works(client)
thread = Thread.new do
client.do("waitfor delay '00:00:05'")
end
sleep 0.1
time = Benchmark.measure do
thread.kill
end
assert time.real < 5Otherwise I might have some time on the weekend to see myself. Nulling out the unblock function would mean the call just continue to run indefinitely, but maybe I am missing something. |
Andy asked whether kill still aborts WAITFOR after removing dbcancel as UBF. Kill returns immediately; join waits for the batch (~5s). Co-authored-by: Cursor <cursoragent@cursor.com>
@andyundso added the test and a bit more which I think was the spirit of your request at https://github.com/rails-sqlserver/tiny_tds/pull/607/changes#diff-fe76b289030e9af8010639512c4d9fab1f5cfd43207ae9137850ae1949dafae1R82 In short, we lose the ability to do Thread#kill and Timeout.timeout with this change and have it behave the way we would like. Here are the actual test results though
The caller would need to use something like client.cancel to break the running connection instead. |
Summary
rb_thread_call_without_gvlcurrently usesdbcancelas the unblock function. MRI invokes that UBF whenever the waiting thread has a pending interrupt, including process-directed signals such asSIGCHLDdelivered to main after another thread spawns a child.dbcancelthen aborts the in-flight batch.Result#eachtreatsFAILas an empty success, so long queries can return[]even though SQL Server produced rows.NULL, NULL) so other Ruby threads can run, but no longer cancels SQL on those interrupts. Client:timeoutis unchanged (dbsetinterrupt).Timeout.timeout/Thread#killwait until the batch finishes or:timeoutfires.Test plan
WAITFOR DELAY; the followingSELECT 42must still return a row.:timeoutviadbsetinterrupt).