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