bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

new module for async-safe spin locks


From: Bruno Haible
Subject: new module for async-safe spin locks
Date: Wed, 01 Jul 2020 23:16:09 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-179-generic; KDE/5.18.0; x86_64; ; )

This patch series adds a module 'asyncsafe-spin', with async-safe spin locks.

What is it?
-----------

An async-safe spin lock is a spin lock that can be used to communicate between
a thread that executes normal code and a thread that executes a signal handler.

The table in section 2.4.3 of
<https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html>
lists the functions that may be called from signal handlers. Unfortunately,
POSIX spin lock functions are not among them. Therefore, a new facility is
needed.

Where is it needed?
-------------------

It is needed anytime where you want to do locking between a signal handler
and normal code.

My use-case is to make the 'clean-temp' module multithread-safe. This module
registers file names (to delete) and file descriptors (to close). The latter
is necessary because POSIX allows for unlink() to fail with error EBUSY when
attempting to delete a file that has an open file descriptor. Now, when both
a normal thread tries to do
  close (fd);
and a signal handler also does
  close (fd);
there is a race condition:
  1. Thread A (normal code) starts to do
     close (fd);
     and is interrupted right when returning from the system call.
  2. An unrelated thread calls open(), and receives a file descriptor
     that is == fd. This is possible, since the kernel will reuse closed
     file descriptors.
  3. Thread A (or another thread B) gets to executes a signal handler
     that also does
       close (fd);
     But this now closes the wrong, unrelated file descriptor!

In more abstract terms: In multithreaded applications, it is forbidden to
close the same fd twice, because you never know what unrelated open() calls
are being executed in other threads. So, the 'close (fd)' must be guarded
by a once-only guard, i.e. effectively a lock.

How is it implemented?
----------------------

Fortunately, GCC has the necessary atomic built-ins for a long time already,
and there are few compilers not based on GCC:
  - AIX xlc and xlclang: are handled through a specific AIX _check_lock()
    function.
  - Solaris cc: are handled through inline asm, based on the code that
    GCC would generate.


2020-07-01  Bruno Haible  <bruno@clisp.org>

        asyncsafe-spin: Add tests.
        * tests/test-asyncsafe-spin1.c: New file.
        * tests/test-asyncsafe-spin2.c: New file, based on tests/test-lock.c and
        tests/test-pthread-spin.c.
        * modules/asyncsafe-spin-tests: New file.

2020-07-01  Bruno Haible  <bruno@clisp.org>

        asyncsafe-spin: New module.
        * lib/asyncsafe-spin.h: New file.
        * lib/asyncsafe-spin.c: New file, based on lib/pthread-spin.c.
        * modules/asyncsafe-spin: New file.


Attachment: 0001-asyncsafe-spin-New-module.patch
Description: Text Data

Attachment: 0002-asyncsafe-spin-Add-tests.patch
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]