This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c/54017] New: Incorrect implementation of infinite loops in OpenMP sections leads to SIGILL
- From: "iliev at rz dot rwth-aachen.de" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Wed, 18 Jul 2012 16:19:57 +0000
- Subject: [Bug c/54017] New: Incorrect implementation of infinite loops in OpenMP sections leads to SIGILL
- Auto-submitted: auto-generated
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54017
Bug #: 54017
Summary: Incorrect implementation of infinite loops in OpenMP
sections leads to SIGILL
Classification: Unclassified
Product: gcc
Version: 4.7.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
AssignedTo: unassigned@gcc.gnu.org
ReportedBy: iliev@rz.rwth-aachen.de
Consider this very simple OpenMP sections code:
int main()
{
#pragma omp parallel sections
{
#pragma omp section
{
for(;1;) {}
}
}
return 0;
}
Since there is only one OpenMP section, if this code is run with more than one
thread, GOMP_sections_start() would return 0 in all but the first thread to
call it. Unfortunately the compiler generates the following assembly code to
test the return value:
movl $1, %edi
call GOMP_sections_start
cmpl $1, %eax
je .L4
.value 0x0b0f
.L4:
jmp .L4
In all threads but the first one the JE instruction would not branch and the
UD2 instruction emitted by __builtin_trap() would get hit and the program will
abort with SIGILL. Tested also with "for(;;) {}" and "while(1) {}" - same
assembly code emitted.
If instead the code of the section is modified to read:
#pragma omp section
{
int i = 1;
for(;i;) {}
}
the produced assembly code correctly handles 0 as the possible return value of
GOMP_sections_next():
call GOMP_sections_next
.L7:
testl %eax, %eax
je .L4
cmpl $1, %eax
je .L5
.value 0x0b0f
.L4:
call GOMP_sections_end_nowait
jmp .L8
.L5:
movl $1, -4(%rbp)
.L6:
cmpl $0, -4(%rbp)
jne .L6
call GOMP_sections_next
jmp .L7
.L8:
leave
Also if at least one another section without infinite loop is added, e.g.:
#pragma omp section
{
for(;1;) {}
}
#pragma omp section
{
int k = 5;
}
return value from GOMP_sections_next() is processed correctly:
call GOMP_sections_next
.L8:
cmpl $1, %eax
je .L6
cmpl $1, %eax
jb .L5
cmpl $2, %eax
je .L7
.value 0x0b0f
.L5:
call GOMP_sections_end_nowait
jmp .L9
.L7:
movl $5, -4(%rbp)
call GOMP_sections_next
jmp .L8
.L6:
jmp .L6
.L9:
leave
The correct behaviour in the first case should be that other threads would wait
infinitely at the barrier in GOMP_parallel_end() and not crash with SIGILL as
in the first case.
Unfortunately I don't have access to GCC versions higher than 4.7.0 but I've
tested it with previous versions down to 4.3.4 with the same result.
Optimisation level has no influence on the problem. It also fails in 32-bit
mode.