Making an ASIO asynchronous operation from flock()
So I need to flock (http://man7.org/linux/man-pages/man2/flock.2.html)
something (pre-existing flock in other piece of software to
interoperate with) and I though: "I think I'm actually starting to
understand ASIO, let's make a proper ASIO asynchronous operation with
flock". Long story short, I now know better: I will never get ASIO.
So my main issues are with the background thread.
According to https://www.boost.org/doc/libs/develop/doc/html/boost_asio/overview/core/thr...
"the threads ... must block all signals". OK, it makes sense, but...
- I can make pthread_sigmask() the first thing once the std::thread
starts executing. But, I can't really guarantee the thread will never
receive a signal, can I? There is a small amount of time between the
thread starting to be able to receive signals and pthread_sigmask()
doing its job. Modifying the signal mask before the background thread
is created (so also from the "not-background" thread) doesn't seem a
lot better.
- How do I cancel the asynchronous operation? flock() is blocking, not
a lot I can do to unblock it. I could send a signal to the background
thread, but... they must be blocked, so no. I can't join the thread
while it's blocked in flock(). So... should it be detached? I could
then maybe just destroy the std::thread, but I still need to call the
handler with boost::asio::error::operation_aborted...
So, my question: I'm making it more difficult than it is? There is
some pattern I should be following which makes all this simple?
See what I have below (sorry for the camel case)
-------------------------------------------------------------------------------
#include
I'd suggest to use fcntl http://man7.org/linux/man-pages/man2/fcntl.2.html which immediately returns an error value if a conflicting lock is attempted to be taken (see under Advisory record locking; F_SETLK). Then you can use a timer to implement retry with exponential back-off or similar.
Alternately, I'd take "block all signals" with a grain of salt. You can use signals from the real-time signal range that isn't used by the system, and install a no-op signal handler. It will interrupt blocking operations (cause them to return with EINTR), but I strongly doubt that it'll affect non-blocking operations. (Signals are delivered on return from kernel space to user space and checking for them "too often" would be a performance penalty.)
-- Stian
________________________________
From: Boost-users
On Mon, 19 Nov 2018 at 19:10, Stian Zeljko Vrba
I'd suggest to use fcntl http://man7.org/linux/man-pages/man2/fcntl.2.html which immediately returns an error value if a conflicting lock is attempted to be taken (see under Advisory record locking; F_SETLK). Then you can use a timer to implement retry with exponential back-off or similar.
Well, I could always call flock with LOCK_NB to implement that same strategy. But I would have liked to let the OS tell me instead of keep asking it.
Alternately, I'd take "block all signals" with a grain of salt. You can use signals from the real-time signal range that isn't used by the system, and install a no-op signal handler. It will interrupt blocking operations (cause them to return with EINTR), but I strongly doubt that it'll affect non-blocking operations. (Signals are delivered on return from kernel space to user space and checking for them "too often" would be a performance penalty.)
I was trying to do it "right" and implement a generic asynchronous operation. The client using such an operation could be using any signal, including the real time signals, for its own purpose. But I tried to do all this thinking "If ASIO does it with the blocking getaddrinfo then I can do it with flock". But after looking in more detail at how getaddrinfo in Linux ASIO works: a) There is a single thread, not one per async_resolv. resolving is not done in parallel, each operation is queued one after the other. b) ip::basic_resolver::cancel() doesn't even really try to cancel the current resolving operation, it just cancels any queued one. It only works because getaddrinfo is "blocking"... with an undocumented, implicit, timeout. 'a' is documented, but 'b' really surprised me since the docs say "This function __forces__ the completion of any pending asynchronous operations on the host resolver". Which I guess is not technically wrong, but still... So I'm leaning towards thinking it can not be done "right" with flock (or getaddrinfo, really), the OS interface is simply not good enough.
participants (2)
-
Cristian Morales Vega
-
Stian Zeljko Vrba