Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20181205212716.sx6ra2xqhuei735q@core.my.home>
Date: Wed, 5 Dec 2018 22:27:16 +0100
From: Ondřej Jirman <megous@...ous.com>
To: musl@...ts.openwall.com
Subject: Re: sem_wait and EINTR

On Wed, Dec 05, 2018 at 08:47:59PM +0100, Markus Wichmann wrote:
> On Wed, Dec 05, 2018 at 07:16:05PM +0000, Orivej Desh wrote:
> > Hi,
> > 
> > musl differs from glibc in that it does not return from sem_wait() on EINTR.
> > This mail [1] explains that this is useful to safeguard the software that does
> > not check sem_wait() return code. However, since glibc does return EINTR, such
> > bugs in the open source software seem to be eventually noticed and fixed.
> > 
> > The musl behaviour has a disadvantage in that it makes sem_wait() difficult to
> > interrupt (and delays the return from sem_timedwait() until the timeout), which
> > is relied upon in particular by multithreaded fuse for breaking out of the
> > main thread waiting loop [2]. IMHO the fuse implementation is sensible, since it
> > looks better than the alternatives I could imagine, and I'm inclined to patch
> > musl like this [3] to meet its expectations.
> > 
> > Am I missing some implications? Would you reconsider returning from sem_wait()
> > on EINTR? Could you suggest a good fix for fuse that does not change musl?
> > 
> > [1] https://www.openwall.com/lists/musl/2018/02/24/3
> > [2] https://github.com/libfuse/libfuse/blob/fuse-3.3.0/lib/fuse_loop_mt.c#L332
> > [3] https://github.com/orivej/musl/commit/c4c38aaab4fc55c23669f7b81386b615609cc3e1
> 
> I wanted to suggest a reworking of libfuse to instead of waiting on a
> semaphore maybe just wait on the actual thread. Then I read the source
> of pthread_join() and noticed that it, too, would hang itself in a loop
> it can't break out of due to EINTR.
> 
> Maybe the simplest solution would be to simply tell libfuse users to
> call fuse_session_exit() from the SIGINT handler if they want this
> behavior to be portable. If fuse_session_exit() is not
> async-signal-safe, then handle SIGINT in another thread using
> pthread_sigmask() and sigwaitinfo().
> 
> In any case, libfuse is relying on behavior not guarenteed by the
> interface. The fact that a certain implementation of the interface
> happens to provide that behavior is irrelevant.

Hello,

It's specified by POSIX:

https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_wait.html

Sates: "The sem_wait() function is interruptible by the delivery of a signal."

> On a practical note, I certainly never expected sem_wait() to be capable
> of failing due to errors other than bad programming before. Coding that
> in would make even simple things like the consumer-producer example by
> Dijkstra look horrible!

There's a difference between pedagogy and production code.

Just wanted to share that I was bitten myself by blindly retrying on EINTR instead
of handling it correctly for the particular program.

For example: When using signalfd, it is critical to be handling EINTR correctly
by getting back to the main loop so that signal handler can be executed (as it
is not executed asynchronously). I certainly would not expect the C library to be
eating EINTRs.

regards,
  o.j.

> Ciao,
> Markus

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.