-
Notifications
You must be signed in to change notification settings - Fork 548
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Avoid GC run between mysql_stmt_execute
and mysql_stmt_store_result
#957
Avoid GC run between mysql_stmt_execute
and mysql_stmt_store_result
#957
Conversation
This fixes a regression caused by brianmario#912 due to calling `rb_funcall` between `mysql_stmt_execute` and `mysql_stmt_store_result`, it will cause `mysql_stmt_close` to be called in wrong order. Fixes brianmario#956.
Nice find! I am worried that this will be fragile, and some other call into Ruby space can still creep in here. I'm looking at whether there is a missing refcount. |
In result.c,
I am wondering how the statement is possibly getting garbage collected at the point of this Your solution avoids
The output I put together a different movement of code and was able to protect against this failure as well. Bottom line, a GC run between |
I found a commit to the sqlite gem showing another case of a hard GC workaround: sparklemotion/sqlite3-ruby@380287a |
Aha, I get it now. The issue is that once a statement begins executing, any other command is invalid such as freeing a much older statement handle, which requires a notification from the client library to the server to release the handle, but isn't valid if the server is in results-streaming-mode. |
Which leads me to wonder... what about streaming results? Yep, that breaks, too! In the repro script:
Even with both of our proposed fixes:
|
According to the last comment on https://dev.mysql.com/doc/refman/5.7/en/commands-out-of-sync.html, and confirmed locally, setting a cursor for the statement execution allows other commands to be processed:
I'm looking at whether the cursor makes sense in all cases, or only in the streaming case. Edit: seems to be fine adding the cursor in both cases, and it completely alleviates the GC problem. |
Yeah, originally fixing the case of I'm closing this in favor of #958. |
This commit fixes two error scenarios. The first is to avoid GC runs between `mysql_stmt_execute` and `mysql_stmt_store_result`. This fixes a regression caused by brianmario#912 due to calling `rb_funcall` between `mysql_stmt_execute` and `mysql_stmt_store_result`. The error in this case is: Commands out of sync; you can't run this command now Thanks to @kamipo for diagnosing the problem and drafting the first PR. The second problem is that in streaming mode, rows are returned to Ruby space one at a time, so garbage collection will naturally occur at any time. By requesting a cursor into the result set, other MySQL commands can be sent on the wire between row fetches. The error in this case is: Row retrieval was canceled by mysql_stmt_close Fixes brianmario#956, updates brianmario#957.
This commit fixes two error scenarios. The first is to avoid GC runs between `mysql_stmt_execute` and `mysql_stmt_store_result`. This fixes a regression caused by brianmario#912 due to calling `rb_funcall` between `mysql_stmt_execute` and `mysql_stmt_store_result`. The error in this case is: Commands out of sync; you can't run this command now Thanks to @kamipo for diagnosing the problem and drafting the first PR. The second problem is that in streaming mode, rows are returned to Ruby space one at a time, so garbage collection will naturally occur at any time. By requesting a cursor into the result set, other MySQL commands can be sent on the wire between row fetches. The error in this case is: Row retrieval was canceled by mysql_stmt_close Fixes brianmario#956, updates brianmario#957.
This commit fixes two error scenarios. The first is to avoid GC runs between `mysql_stmt_execute` and `mysql_stmt_store_result`. This fixes a regression caused by brianmario#912 due to calling `rb_funcall` between `mysql_stmt_execute` and `mysql_stmt_store_result`. The error in this case is: Commands out of sync; you can't run this command now Thanks to @kamipo for diagnosing the problem and drafting the first PR. The second problem is that in streaming mode, rows are returned to Ruby space one at a time, so garbage collection will naturally occur at any time. By requesting a cursor into the result set, other MySQL commands can be sent on the wire between row fetches. The error in this case is: Row retrieval was canceled by mysql_stmt_close Fixes brianmario#956, updates brianmario#957.
This commit fixes two error scenarios. The first is to avoid GC runs between `mysql_stmt_execute` and `mysql_stmt_store_result`. This fixes a regression caused by #912 due to calling `rb_funcall` between `mysql_stmt_execute` and `mysql_stmt_store_result`. The error in this case is: Commands out of sync; you can't run this command now Thanks to @kamipo for diagnosing the problem and drafting the first PR. The second problem is that in streaming mode, rows are returned to Ruby space one at a time, so garbage collection will naturally occur at any time. By requesting a cursor into the result set, other MySQL commands can be sent on the wire between row fetches. The error in this case is: Row retrieval was canceled by mysql_stmt_close Fixes #956, updates #957.
This fixes a regression caused by #912 due to calling
rb_funcall
between
mysql_stmt_execute
andmysql_stmt_store_result
, it willcause
mysql_stmt_close
to be called in wrong order.Fixes #956.