Comments (3)
When calling rb_thread_call_without_gvl
, its third parameter is rb_unblock_function_t *ubf
. This is an "unblock function": Ruby will call this when a signal is sent to the app, and this function is supposed to do whatever necessary to abort the operation that the func
function is doing. You passed RUBY_UBF_IO
but this is actually a no-op function, because Ruby internally has all sorts of IO cancellation mechanisms that allows it to abort even without an unblock function that does anything.
So what does your unblock function need to do? There are a couple of methods (which I haven't tested, but should work), all of which need changes beyond just writing an unblock function.
First, there is CURLOPT_READFUNCTION
to set your own read function. By default libcurl uses the read() system call on a blocking socket. You can set that option to your own function which polls() two file descriptors: the actual socket, as well as a "cancellation pipe". If the poll says that the actual socket is readable, read() from it. If the poll says that the cancellation pipe is readable, return CURL_READFUNC_ABORT to tell libcurl that you want to abort. The unblock function simply closes the cancellation pipe to make it readable. The cancellation pipe is a pipe that you that you create beforehand, before each curl_easy_perform
executes. The cancellation pipe pattern is a common pattern in Unix server software to stop an event loop.
The other alternative is to have an actual event loop (maybe using libev or libevent, or possibly one written by yourself) and integrate libcurl into that event loop. Your unblock function then simply cancels the event loop using whatever mechanism is appropriate for your event loop implementation. The mechanism in libcurl that allows event loop integration is libcurl-multi.
from patron.
@FooBarWidget thanks for your explanation! The plot thickens since I found something peculiar. I did indeed experiment with a custom ubf. If I take an implementation like this:
#include <stdio.h>
void session_ubf_abort(void* patron_state) {
struct patron_curl_state* state = (struct patron_curl_state*) patron_state;
printf("Aborting in unblock fun\n");
state->interrupt = INTERRUPT_ABORT; // Next iteration of the progress callback will abort the CURL call if this is set, so there is a delay but it's not significant
}
and run a test case like this:
it "is able to terminate main thread that is running a slow request" do
session = Patron::Session.new
session.timeout = 40
session.base_url = "http://localhost:9001"
session.get("/slow")
end
then I am able to use Ctrl+C to abort. I also do see that the unblock fun gets called (that's why the prinft). The interrupt gets set for libCURL and libCURL then aborts in it's progress callback function - all is nice and dandy. Doing a thread kill also works:
it "is able to terminate the thread that is running a slow request" do
t = Thread.new do
session = Patron::Session.new
session.timeout = 40
session.base_url = "http://localhost:9001"
session.get("/slow")
end
sleep 3
t.kill
end
I do get feedback on the terminal that the UBF did get triggered.
This, however, does not work (and this most closely matches what I am after):
it "is able to terminate the thread that is running a slow request" do
Thread.new do
session = Patron::Session.new
session.timeout = 40
session.base_url = "http://localhost:9001"
session.get("/slow")
end
sleep 60 # When sleeping here Ruby is doing useful stuff, but Ctrl+C does nothing
end
The progress callback function we set for libCURL is getting called still, so that's fine - but Ruby never calls the UBF. So whichever solution I choose from what you have outlined I don't understand how to receive the signal in the first place when I have multiple threads running :-(
from patron.
A Ctrl-C only kills the main thread. If you want any other threads to be killed as well then you need to propagate that signal to those threads manually.
from patron.
Related Issues (20)
- Release 0.8 HOT 1
- Automate the Patron release process HOT 5
- Idea: Connection pooling using curl_multi HOT 4
- Add streaming upload/download support HOT 1
- Release new version HOT 2
- The Hive copyright comment HOT 1
- Headers aren't parsed correctly for first request when connection is proxied HOT 1
- Redirect handling inconsistency HOT 3
- VCR issues after upgrading patron 0.10.0 -> 0.11.1 HOT 6
- RFC: Streaming response bodies HOT 8
- PATCH method doesn't send body HOT 4
- Gem not installed to ruby 2.1.2 HOT 1
- how to set ssl client_key / client_cert ? HOT 6
- Request: Render full server response as a string HOT 1
- Figure out the actual set of supported HTTP verbs
- --http1.1 option please HOT 1
- "checking for ruby/thread.h... *** extconf.rb failed ***" when installing on google/cloud-sdk:alpine docker image HOT 1
- one rspec test fails on Arch Linux
- Basic Auth HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from patron.