fix severe bug causing deadlocks
This commit is contained in:
parent
4e26e066ad
commit
7b6b1f32d5
|
@ -62,6 +62,6 @@ macro app(def)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function serve(h::App, context, host = ip"127.0.0.1", port = 1965; kws...)
|
function serve(h::App, host = ip"127.0.0.1", port = 1965; kws...)
|
||||||
@async listen((req) -> h.warez(req), context, host, port; kws...)
|
@async listen((req) -> h.warez(req), host, port; kws...)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
function listen(f,
|
function listen(f,
|
||||||
context::SSLContext,
|
init_context,
|
||||||
host::Union{IPAddr, String} = Sockets.localhost,
|
host::Union{IPAddr, String} = Sockets.localhost,
|
||||||
port::Integer = 1965
|
port::Integer = 1965
|
||||||
;
|
;
|
||||||
|
@ -9,35 +9,36 @@ function listen(f,
|
||||||
|
|
||||||
server = Sockets.listen(Sockets.InetAddr(host, port))
|
server = Sockets.listen(Sockets.InetAddr(host, port))
|
||||||
verbose && @info "Listening on: $host:$port"
|
verbose && @info "Listening on: $host:$port"
|
||||||
|
return listenloop(f, server, init_context, connection_count, readtimeout, verbose)
|
||||||
return listenloop(f, server, context, connection_count, readtimeout, verbose)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
""""
|
""""
|
||||||
Main server loop.
|
Main server loop.
|
||||||
Accepts new tcp connections and spawns async tasks to handle them."
|
Accepts new tcp connections and spawns async tasks to handle them."
|
||||||
"""
|
"""
|
||||||
function listenloop(f, server, context, connection_count, readtimeout, verbose)
|
function listenloop(f, server, init_context, connection_count, readtimeout, verbose)
|
||||||
count = 1
|
count = 1
|
||||||
while isopen(server)
|
while isopen(server)
|
||||||
try
|
try
|
||||||
# @info "Ready to accept new connection"
|
verbose && @info "Ready to accept new connection"
|
||||||
io = accept(server)
|
io = accept(server)
|
||||||
if io === nothing
|
if isnothing(io)
|
||||||
verbose && @warn "unable to accept new connection"
|
verbose && @warn "unable to accept new connection"
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
connection_count[] += 1
|
connection_count[] += 1
|
||||||
|
verbose && @info "$(connection_count[]) total connections"
|
||||||
@async try
|
@async try
|
||||||
handle_connection(f, server, context, io, verbose)
|
handle_connection(f, server, init_context, io, verbose)
|
||||||
catch e
|
catch e
|
||||||
if e isa Base.IOError && e.code == -54
|
if e isa Base.IOError && e.code in (-54, -104)
|
||||||
verbose && @warn "connection reset by peer (ECONNRESET)"
|
verbose && @warn "connection reset by peer (ECONNRESET)"
|
||||||
else
|
else
|
||||||
@error exception=(e, stacktrace(catch_backtrace()))
|
@warn exception=(e, stacktrace(catch_backtrace()))
|
||||||
end
|
end
|
||||||
finally
|
finally
|
||||||
connection_count[] -= 1
|
connection_count[] -= 1
|
||||||
|
verbose && @info "$(connection_count[]) total connections"
|
||||||
# handle_connection is in charge of closing the underlying io
|
# handle_connection is in charge of closing the underlying io
|
||||||
end
|
end
|
||||||
catch e
|
catch e
|
||||||
|
@ -50,35 +51,32 @@ function listenloop(f, server, context, connection_count, readtimeout, verbose)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
count += 1
|
count += 1
|
||||||
|
verbose && @info "Responded to $(count) clients in total"
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
function handle_connection(f, server, context, io, verbose)
|
function handle_connection(f, server, init_context, io, verbose)
|
||||||
client = SSLClient(context, io)
|
client = SSLClient(init_context(), io)
|
||||||
while isopen(server) && isopen(io)
|
|
||||||
try
|
try
|
||||||
while true
|
while isopen(server) && isopen(io)
|
||||||
if isreadable(io) && length(client.write_buf) == 0
|
if isreadable(io) && length(client.write_buf) == 0
|
||||||
# verbose && println("do_read")
|
|
||||||
if OpenSSL.do_sock_read(client) == -1
|
if OpenSSL.do_sock_read(client) == -1
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if iswritable(io) && length(client.write_buf) > 0
|
if iswritable(io) && length(client.write_buf) > 0
|
||||||
# verbose && println("do_write")
|
verbose && println("do_write")
|
||||||
if OpenSSL.do_sock_write(client) == -1
|
if OpenSSL.do_sock_write(client) == -1
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# verbose && println("end loop")
|
|
||||||
if OpenSSL.ssl_init_finished(client)
|
if OpenSSL.ssl_init_finished(client)
|
||||||
# verbose && println("init_finished")
|
verbose && println("init_finished")
|
||||||
# TODO: add a timeout!
|
# TODO: add a timeout!
|
||||||
while isopen(server) && isopen(io) &&
|
while isopen(server) && isopen(io) &&
|
||||||
(length(client.context.data) < 2 ||
|
(length(client.context.data) < 2 ||
|
||||||
client.context.data[end-1:end] != UInt8['\r', '\n'])
|
client.context.data[end-1:end] != UInt8['\r', '\n'])
|
||||||
# println("HERE")
|
|
||||||
OpenSSL.do_sock_read(client)
|
OpenSSL.do_sock_read(client)
|
||||||
end
|
end
|
||||||
f(GeminiRequest(Connection(server, client),
|
f(GeminiRequest(Connection(server, client),
|
||||||
|
@ -92,5 +90,4 @@ function handle_connection(f, server, context, io, verbose)
|
||||||
finally
|
finally
|
||||||
close(client)
|
close(client)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue