Package: g++-15
Version: 15.3.0-2
Severity: normal
Tags: upstream

Dear Maintainer,

I implements a solution of the classical "dining philosophers" synchronisation
problem using C++-20 semaphores:
Solution implemented: 1 semaphore per fork, 1 counting semaphore to avoid that
NUM_THREADS forks are taken one per thread, thus avoiding dealock.

I compile with: g++-15 -std=gnu++23 -g philo_bug.cc -o philo_bug
on a intel core i7 (8 cores)
vendor_id       : GenuineIntel
cpu family      : 6
model           : 141
model name      : 11th Gen Intel(R) Core(TM) i7-11850H @ 2.50GHz

The binary deadlocks often (1/4 time in gdb) when compiled with g++-15 (Debian
15.3.0-2) or g++-14 (14.4.0-1).
It does NOT deadlock when compiled with g++-16 or clang++-21,22,23

#include <thread>
#include <semaphore>

using namespace std;

constexpr int NUM_THREADS = 5;
constexpr int ROUND = 20000;

counting_semaphore<NUM_THREADS> nbtaken{NUM_THREADS - 1};
array<binary_semaphore, NUM_THREADS> forks = {binary_semaphore{1},
binary_semaphore{1},
    binary_semaphore{1}, binary_semaphore{1}, binary_semaphore{1}};

void takeForks(int me) {

  nbtaken.acquire();
  forks.at(me).acquire();
  forks.at((me + 1) % NUM_THREADS).acquire();
  nbtaken.release();
}

void releaseForks(int me) {
    forks.at(me).release();
    forks.at((me+1)%NUM_THREADS).release();
}

void philo(int me) {
  for (int i = 0; i < ROUND; i++) {
    takeForks(me);
    releaseForks(me);
  }
}

int main() {
  vector<unique_ptr<thread>> ths;
  for (int i = 0; i < NUM_THREADS; i++)
      ths.push_back(unique_ptr<thread>(new thread{philo, i}));

  for (auto &t : ths) {
    t->join();
  }
  return 0;
}

Checking with gdb at a deadlock time, one of the forks is at 1 but the
corresponding thread is still blocked in the acquire.

Following a gdb session example: thread(me == 1) is blocked acquiring forks[2]
but the counter of semaphore forks[2] is at 1
Reading symbols from ./philo_bug...
(gdb) run
Starting program: /home/gregory/ensimag-app.gitlabensimag/tp/sujets/philo_bug
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff79136c0 (LWP 159677)]
[New Thread 0x7ffff71126c0 (LWP 159678)]
[New Thread 0x7ffff69116c0 (LWP 159679)]
[New Thread 0x7ffff61106c0 (LWP 159680)]
[New Thread 0x7ffff590f6c0 (LWP 159681)]
^C
Thread 1 "philo_bug" received signal SIGINT, Interrupt.
__syscall_cancel_arch () at
../sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S:56
⚠️ warning: 56  ../sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S: Aucun
fichier ou dossier de ce nom
(gdb) p forks
$1 = {_M_elems = {{_M_sem = {static _S_max = 2147483647, _M_counter = 0}},
{_M_sem = {static _S_max = 2147483647,
        _M_counter = 0}}, {_M_sem = {static _S_max = 2147483647, _M_counter =
1}}, {_M_sem = {static _S_max = 2147483647,
        _M_counter = 0}}, {_M_sem = {static _S_max = 2147483647, _M_counter =
0}}}}
(gdb) thread 4
[Switching to thread 4 (Thread 0x7ffff69116c0 (LWP 159679))]
#0  syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
⚠️ warning: 38  ../sysdeps/unix/sysv/linux/x86_64/syscall.S: Aucun fichier ou
dossier de ce nom
(gdb) up 5
#5  0x0000555555555253 in takeForks (me=2) at philo_bug.cc:17
17        nbtaken.acquire();
(gdb) thread 3
[Switching to thread 3 (Thread 0x7ffff71126c0 (LWP 159678))]
#0  syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
⚠️ warning: 38  ../sysdeps/unix/sysv/linux/x86_64/syscall.S: Aucun fichier ou
dossier de ce nom
(gdb) up 5
#5  0x00005555555552b9 in takeForks (me=1) at philo_bug.cc:19
19        forks.at((me + 1) % NUM_THREADS).acquire();
(gdb) p me
$2 = 1
(gdb) p forks[2]
$3 = {_M_sem = {static _S_max = 2147483647, _M_counter = 1}}
(gdb)



-- System Information:
Debian Release: forky/sid
  APT prefers unstable
  APT policy: (990, 'unstable'), (500, 'testing'), (500, 'stable'), (1, 
'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 7.1.5+deb14-amd64 (SMP w/16 CPU threads; PREEMPT)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8), 
LANGUAGE=fr:en_US
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages g++-15 depends on:
ii  g++-15-x86-64-linux-gnu  15.3.0-2
ii  gcc-15                   15.3.0-2
ii  gcc-15-base              15.3.0-2

g++-15 recommends no packages.

Versions of packages g++-15 suggests:
pn  g++-15-multilib  <none>
ii  gcc-15-doc       15.2.0-1

-- no debconf information

Reply via email to