Skip to content

Commit 2115a86

Browse files
committed
fix: handle FDWatcher exception on closed sockets
Adding checks to handle exception thrown while constructing FDWatcher if the socket handle is closed. Also checking the curl return code while adding handle to multi, and not proceeding if that failed. Should fix #253
1 parent 89d3c7d commit 2115a86

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

src/Curl/Multi.jl

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,18 @@ end
4343

4444
function add_handle(multi::Multi, easy::Easy)
4545
connect_semaphore_acquire(easy)
46-
lock(multi.lock) do
46+
added = lock(multi.lock) do
4747
if isempty(multi.easies)
4848
preserve_handle(multi)
4949
end
5050
push!(multi.easies, easy)
5151
init!(multi)
5252
@check curl_multi_add_handle(multi.handle, easy.handle)
5353
end
54+
if added != 0
55+
connect_semaphore_release(easy)
56+
end
57+
return added
5458
end
5559

5660
const MULTIS_LOCK = Base.ReentrantLock()
@@ -170,7 +174,22 @@ function socket_callback(
170174
if action in (CURL_POLL_IN, CURL_POLL_OUT, CURL_POLL_INOUT)
171175
readable = action in (CURL_POLL_IN, CURL_POLL_INOUT)
172176
writable = action in (CURL_POLL_OUT, CURL_POLL_INOUT)
173-
watcher = FDWatcher(OS_HANDLE(sock), readable, writable)
177+
watcher = try
178+
FDWatcher(OS_HANDLE(sock), readable, writable)
179+
catch watcher_ex
180+
if watcher_ex isa Base.IOError
181+
task = @async begin
182+
lock(multi.lock) do
183+
@check curl_multi_socket_action(multi.handle, sock, CURL_CSELECT_ERR)
184+
check_multi_info(multi)
185+
end
186+
end
187+
@isdefined(errormonitor) && errormonitor(task)
188+
nothing
189+
else
190+
rethrow()
191+
end
192+
end
174193
preserve_handle(watcher)
175194
watcher_p = pointer_from_objref(watcher)
176195
@check curl_multi_assign(multi.handle, sock, watcher_p)

src/Downloads.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,11 @@ function request(
395395
easy_hook(downloader, easy, info)
396396

397397
# do the request
398-
add_handle(downloader.multi, easy)
398+
add_handle_error = add_handle(downloader.multi, easy)
399+
if add_handle_error != 0
400+
no_response = Response(nothing, "", 0, "", [])
401+
throw(RequestError(url, add_handle_error, "", no_response))
402+
end
399403
interrupted = Threads.Atomic{Bool}(false)
400404
if interrupt !== nothing
401405
interrupt_task = @async begin

0 commit comments

Comments
 (0)