Hi,
Is it a non-blocking alternative to recvfrom()
?
My application consist of two threads, where one of them is listening on a socket for incoming packets. The other thread then sends a signal to this thread after x seconds to tell it to return. This is done by using a Channel
. But, it seems that recvfrom
is blocking so that it don’t see that a signal is received on the channel… Does anyone have any suggestions to how I can solve this?
Timer
on the waiting thread? No need for inter-thread communication here.
No I don’t use a Timer
here. Just two threads, where one of them need to tell the other to stop. But it will not see this stop message, because recvfrom
is blocking…
Yes, I got that. I was suggesting to use a Timer
on the thread that’s waiting in recvfrom
instead of using a Channel
for that. Using a Channel
means you have to actively check it, a Timer
will interrupt you.
I want my main thread be the one that tells the second thread (which has the recvfrom
) to quit. So I don’t want my second thread to tell itself when to quit…
Well, as far as I know, there is no nonblocking recvfrom
(assuming you’re talking about Sockets.recvfrom
). There’s also no good way to interrupt a running async task, which is why I suggested using a Timer
to periodically interrupt the blocking behavior, then check the Channel
for whether or not the thread should terminate or not, then relaunch a Timer
and block again.
recvfrom is also written in Julia, you could roll your own
https://github.com/JuliaLang/julia/blob/master/stdlib/Sockets/src/Sockets.jl#L331-L365
I tried implementing a MWE now, and to my surprise this works fine. So after 2 seconds, the signal is sent, and the thread successfully quits… But, why does this work? I thought recvfrom
was a blocking call?
using Sockets
function recv_data()
insock = UDPSocket()
from = Sockets.InetAddr(ip"127.0.0.1", 3000)
bind(insock, from.host, from.port)
while !(isready(running) && fetch(running) isa Stop)
from, data = recvfrom(insock)
end
close(insock)
return
end
struct Stop end
running = Channel{Stop}(1)
t1 = @Threads.spawn recv_data()
sleep(2)
put!(running, Stop())
The docs say it blocks
Read a UDP packet from the specified socket, and return the bytes received. This call blocks.
Yes, it does. But then I thought in MWE that recv_data()
would not exit as it does, because in the while
-loop the recvfrom
will block… But it do exit successfully… Why??
Are you sure this is working? It doesn’t appear it is to me:
using Sockets
function recv_data()
insock = UDPSocket()
from = Sockets.InetAddr(ip"127.0.0.1", 3000)
bind(insock, from.host, from.port)
while !(isready(running) && fetch(running) isa Stop)
println("listening...")
from, data = recvfrom(insock)
end
println("done.")
close(insock)
return
end
struct Stop end
running = Channel{Stop}(1)
t1 = @Threads.spawn recv_data()
sleep(2)
put!(running, Stop())
sleep(2)
@show istaskdone(t1)
Outputs:
listening...
istaskdone(t1) = false
Which indicates that the recvfrom
call is blocking t1
from exiting.