Re: Closing an accepting BSD socket from a different thread


Paul Sokolovsky
 

Hello,

On Thu, 23 May 2019 09:10:38 +0200
Stephan Gatzka <stephan.gatzka@...> wrote:

Hello Paul!

Thanks for the answer.


Paradigmatically correct approach to this situation is:

1. Avoid sharing I/O resources (not just sockets) across different
threads.
2. If/when you can't avoid it, you need to synchronize access to
those resources from different threads using synchronization
primitives (mutexes, semaphores, etc.)
Sure, no doubt on that. The problem is, that I need a mechanism to
"unblock" the accept.
Yes, I could use non-blocking sockets with poll(),
For completeness of covering the topic, the sockets for poll() don't
have to be non-blocking.

but I also found
no easy to use mechanism to "unblock" poll().
You can pass a timeout after which poll() will "unblock".

I can't just send a
signal to that thread which called poll() like it would work in Linux.
Yes, Unix signals aren't implemented in Zephyr, and I personally don't
see them coming anytime soon due to reasons hinted by Marc in another
mail. (But then somehow who may contribute a high-quality
implementation of them may think otherwise).

Eventually, we'll need to catch and fix such cases. But the only
visible effect for well-behaving applications following the
guidelines above will be bloating code size in the Zephyr network
stack/socket implementation (so hopefully, we won't get bad
community stereotypes due to that). If you have a small
reproduction testcase for the issue, definitely please submit it at
https://github.com/zephyrproject-rtos/zephyr/issues
Will do.

My question is how I can safely "unblock" the thread waiting in the
zsock_accept()?
A way to not block forever in accept() call is to use timed poll()
on that socket. The thread issuing the poll() call would be the best
party to know when to close this socket (e.g., if there's no
activity during some period of time). Other threads could signal the
owner thread that they want something to be done to the socket via
flag variables. E.g., following is a well-know pattern:

=== main loop thread ===
while (!should_exit) {
...
poll(..., MAIN_LOOP_PERIOD);
...
}
close(...);
exit();

=== other threads ===
should_exit = true;
Yeah sure, put this is polling and a waste of resources.
No, it's not, in a sense of "busy-wait polling". It's a well-known low
duty cycle design pattern. If you poll() with timeout of 100ms and then
wake up for 1ms, you you're sleeping 99% of time, 1% duty cycle. But 1ms
is a huge period of time, it's 100,000 cycles of a 100MHz CPU. If you
optimize that to some 1000s of cycles on event-free wakeups, you can
achieve >0.1% duty cycle.

That I
really don't like, especially an small battery powered systems.
Sure, Zephyr needs a lot of optimizations of low-power usage, any
contribution is welcome.

No, the only possible solution I see is an additional socket
connection via localhost which "signals" poll() and afterwards I can
see what needs to be done (e.g. calling close()).
There was actually a patch submitted to Zephyr mainline which used that
technique. I dissuaded the author from following that approach, as I
consider it to be definitely too heavy-weight to seriously used in
mainline. But you definitely can use it at prototyping stage on your
app's side.

The reason for my question is that I need to implement an event loop
based system. I need events for sockets, timers, DNS.
The idea is to use e zephyr message queue with a thread reading from
the queue and calling the callback functions.
Right, so everyone wants Zephyr to be able to do advanced things, and
everyone agrees that it's too young yet and missing a lot of such
advanced functionality. My response tried to outline ways to get
started right away, albeit with some compromises here and there.
Hopefully, such a smooth start-up curve would motivate you to
contribute for resolution of the issues you write about.

An alternative is to wait until someone implements it all. As an
example, I want to implement epoll() for 2 years now. And I can't even
bootstrap a good discussion of it (at least shoot a brain-dump message
once: https://lists.zephyrproject.org/g/devel/topic/25004178) - we have
much more mundane things to do so far :-I.


Regards,
Stephan

--
Best Regards,
Paul

Linaro.org | Open source software for ARM SoCs
Follow Linaro: http://www.facebook.com/pages/Linaro
http://twitter.com/#!/linaroorg - http://www.linaro.org/linaro-blog

Join users@lists.zephyrproject.org to automatically receive all group messages.