https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127738
Bug ID: 127738
Summary: caf_shmem: FORM TEAM id collision, segfault on pool
exhaustion, leaked shared memory
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libfortran
Assignee: unassigned at gcc dot gnu.org
Reporter: jvdelisle at gcc dot gnu.org
Target Milestone: ---
Thanks to some automated testing:
Three independent defects in libcaf_shmem (-fcoarray=shared), found
while measuring the memory used by coarrays allocated in child teams.
All three reproduce on trunk 20261002.
1. FORM TEAM can pick up the shared data of another team.
_gfortran_caf_form_team derives the id of a team's shared memory from
(parent lastmemid << image_size_shift) + team_no + teams_count
where teams_count counts the FORM TEAM statements executed so far.
The sum is not unique: forming team number 2 and then team number 1
in the same parent team gives 2 + 0 == 1 + 1, so the second FORM TEAM
finds the image map of the first team. Depending on the statements
this fails with "Can not assign new image index in FORM TEAM" or "The
NEW_INDEX of FORM TEAMs has to be unique", and it can also join images
into the wrong team. Forming teams in a loop runs into it easily.
---- team_id.f90 ----
program team_id
use iso_fortran_env, only : team_type
implicit none
type(team_type) :: t1, t2
integer :: me
me = this_image ()
form team (2, t1)
form team (1, t2)
change team (t2)
print '(a,i0,a,i0,a,i0)', 'image ', me, ': team ', team_number (), &
', num_images ', num_images ()
end team
end program team_id
----
$ gfortran -fcoarray=shared team_id.f90 && GFORTRAN_NUM_IMAGES=4 ./a.out
Fortran runtime error: Can not assign new image index in FORM TEAM.
(on every image; expected: each image in team 1 of 4 images)
2. ALLOCATE (stat=) of a coarray does not report an exhausted shared
memory pool.
When the shared memory pool (GFORTRAN_SHARED_MEMORY_SIZE) cannot hold
the coarray, ALLOCATE returns stat=0 and the first access to the
coarray segfaults, instead of the allocation failing with a nonzero
stat (or error termination without stat=).
---- pool_stat.f90 ----
program pool_stat
implicit none
integer(8), allocatable :: a(:)[:]
integer :: st
st = 0
! 8 MiB per image; more than the shared memory pool for 8 images
allocate (a(1048576)[*], stat=st)
if (st == 0) then
a = this_image ()
print '(a,i0,a)', 'image ', this_image (), ': allocated'
else
print '(a,i0,a,i0)', 'image ', this_image (), ': stat ', st
end if
end program pool_stat
----
$ gfortran -fcoarray=shared -g pool_stat.f90
$ GFORTRAN_NUM_IMAGES=8 GFORTRAN_SHARED_MEMORY_SIZE=32M ./a.out
Program received signal SIGSEGV: Segmentation fault
at pool_stat.f90:10 (a = this_image ())
With GFORTRAN_SHARED_MEMORY_SIZE=128M all images allocate.
3. The shared memory object is left behind when the program is
stopped by a signal.
Normal termination, STOP, ERROR STOP, FAIL IMAGE and an image killed
by a signal all remove /dev/shm/gfor-shm-<pid>. When the supervisor
process itself receives SIGTERM or SIGINT (a timeout, ^C), it kills
the images and exits without unlinking the object, so every such run
leaks one; a machine that runs the testsuite collects hundreds of
them.
---- sleep.f90 ----
program sleep_forever
implicit none
sync all
do
end do
end program sleep_forever