[Interest] proper (silent) exit in response to SIGHUP?

Thiago Macieira thiago.macieira at intel.com
Sun Oct 14 01:20:24 CEST 2018


On Saturday, 13 October 2018 01:15:00 PDT René J. V. Bertin wrote:
> Thiago Macieira wrote:
> > Yes, but no one uses them on Windows. In the UNIX world, they're used and
> > part of system administration.
> 
> So you're saying there's no point in trying to find an MSWin alternative for
> pipe() because chances are too slim that the application would ever receive
> a signal? I forgot to mention that aspect before: pipe() not being
> cross-platform was another reason I have been looking for alternative
> approaches.

I'm saying there's no point in installing signal handlers on Windows in the 
first place, so you don't need to figure out how to create a pipe. Anyway, the 
alternative is CreateEvent and SetEvent.

> If so, there's the alternative of using a semaphore (not a QSemaphore;
> sem_post() is safe according to the POSIX docs) though that would probably
> require a separate thread and a trick to rearm the mechanism. A Qt wrapper
> around "native" semaphores could have made this easier.

Or you can use an eventfd in a EFD_SEMAPHORE mode.

Do you realise that the cost of starting a thread is much higher than the cost 
of a pipe? Not to mention that using QThread will create a pipe anyway, so 
you'd need to drop down to low-level primitives (pthread, Win32) to get away 
from it.

> > Get your vendor to provide an object with a single file descriptor then.
> 
> Sorry, vendor? Object?

You were complaining that pipes are too costly. Ok, so get your OS vendor to 
create an equivalent to Linux's eventfd(). That was state of the art 11 years 
ago, so other vendors should be able to catch up or offer a reasonable 
alternative.

> > FreeBSD: back then, FreeBSD supported more than 256 file descriptors per
> > process. So I know for a fact that FreeBSD (and thus Darwin today) do
> > support more. It may not be the default, so just adjust it.
> 
> The QFSW documentation still mentions the 256 fd limit explicitly.

Yes, some systems do. But you can raise the limit.

> There must still be a QTBUG somewhere about the QFSW saturation in Qt4, and
> then there's an open issue about QtHelp which suffers from the same open
> file descriptor limit on Mac (and presumably *BSD). Add too many .qch files
> to a collection and at some point the Assistant (or apps doing similar
> things) will crash. I don't have access to my Mac right now so I can't
> confirm whether I maxed out the open fd limit or whether the system call is
> being ignored.

Raise the limit! 
	man 1 ulimit
	man 2 setrlimit

> > allocation-free for the typical cases, your code would have to contend
> > with
> > the untypical case and would therefore be unsafe.
> 
> Would it? A signal handler can be unique and work with structures that have
> been preallocated. Typically you'd only need to update the signal number
> which doesn't require allocating anything.

Correct. That's why we use the pipe or eventfd trick. You could store more 
information if you wanted in a pre-allocated structure too.

> I was halfway through a PoC implementation using a pre-allocated custom
> QEvent when I realised that QCoreApplication::sendEvent() is apparently
> synchronous so I'd need QCoreApplication::postEvent(). And that one does
> all kind of unsafe things. Transferring ownership of the QEvent wouldn't be
> a problem (just allocate a new one in the actual signal handler, if needed)
> but postEvent() also locks a mutex.

"just allocate in the actual signal handler" is exactly what you mustn't do, 
since malloc() is not async-signal-safe. You can deadlock or corrupt memory if 
you try that.

You could pre-allocate the event before the signal and then you can transfer 
ownership. But postEvent() still needs to manage a queue and that may need to 
allocate memory. To support an allocation-free event posting, we'd need to 
make sure the queue always has some buffer free and since this buffer can't be 
managed by malloc(), we conclude it must be a static buffer that must never be 
allowed to fill. Except when we want to fill it. So immediate corollary is 
that posting from a Unix signal handler necessarily requires a function other 
than postEvent().

Which in turn means this doesn't need to be in Qt at all. Simply create your 
own event store and write to that from your signal handler. You can wake up 
the thread by using 
	QAbstractEventDispatcher::instance(thread)->wakeUp();
[note how that *is* writing to a pipe or an eventfd]

The next thing is to make sure you get to check your buffer from that thread 
at opportune moments. For example, you can use a periodic timer or connect a 
slot to the dispatcher's awake() signal. I recommend the latter.

Note you'll be trading application memory and CPU cycles on *every* *event* 
*loop* for a pipe. Is that worth the cost?

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center






More information about the Interest mailing list