Search code examples
linuxfortrangfortranintel-fortranintel-oneapi

tracebackqq() with ifort leads to segmentation fault


Why does the following code lead to segmentation fault when compiled with ifort?

! testtrb.f90
program testtrb
    call tracebackqq()  ! This is for ifort
    !call backtrace()  ! This is for gfortran 
    print '(/1A/)', 'Finish.'
end program testtrb

Executing ifort testtrb.f90 ; ./a.out, I got

forrtl: severe (174): SIGSEGV, segmentation fault occurred
Image              PC                Routine            Line        Source             
a.out              0000000000409FFA  Unknown               Unknown  Unknown
libpthread-2.31.s  00007F6E2C9903C0  Unknown               Unknown  Unknown
a.out              000000000040746D  Unknown               Unknown  Unknown
a.out              000000000040383B  Unknown               Unknown  Unknown
a.out              00000000004037E2  Unknown               Unknown  Unknown
libc-2.31.so       00007F6E2C7B00B3  __libc_start_main     Unknown  Unknown
a.out              00000000004036EE  Unknown               Unknown  Unknown

The return of ifort --version is ifort (IFORT) 19.1.1.217 20200306. I also tried ifort (IFORT) 2021.1 Beta 20201112, the result being similar. The value of uname -r is 5.9.0-050900-generic, if it is helpful.

However, changing tracebackqq to backtrace and runing gfortran testtrb.f90 ; ./a.out , I get

#0  0x7f789588ad3a
#1  0x557b8f35119d
#2  0x557b8f351254
#3  0x7f789569f0b2
#4  0x557b8f3510cd
#5  0xffffffffffffffff

Finish.

This seems correct.

So why does tracebackqq give rise to SIGSEGV?

Any comments or criticism will be appreciated. Thanks.


Solution

  • The program is not behaving as you expect for two reasons, both documented at https://www.intel.com/content/www/us/en/develop/documentation/fortran-compiler-oneapi-dev-guide-and-reference/top/language-reference/a-to-z-reference/t-to-z/tracebackqq.html

    1. Tracebackqq has optional arguments. It thus requires an interface to be in scope at the calling point. This is achieved by using the ifcore module
    2. Bizarrely by default tracebackqq terminates execution. To have the program continue execution you need to provide a non-default user_exit_code

    So compiling and running the provided code on the login node of our local cluster I get the same behaviour as above:

    [ijb@login12(arcus-b) stack]$ cat tb.f90
    ! testtrb.f90
    program testtrb
        call tracebackqq()  ! This is for ifort
        !call backtrace()  ! This is for gfortran 
        print '(/1A/)', 'Finish.'
    end program testtrb
    [ijb@login12(arcus-b) stack]$ ifort --version
    ifort (IFORT) 19.0.1.144 20181018
    Copyright (C) 1985-2018 Intel Corporation.  All rights reserved.
    
    [ijb@login12(arcus-b) stack]$ ifort -g -traceback tb.f90
    [ijb@login12(arcus-b) stack]$ ./a.out
    forrtl: severe (174): SIGSEGV, segmentation fault occurred
    Image              PC                Routine            Line        Source             
    a.out              0000000000409A03  Unknown               Unknown  Unknown
    libpthread-2.12.s  000000381E40F710  Unknown               Unknown  Unknown
    a.out              00000000004800CF  Unknown               Unknown  Unknown
    a.out              0000000000406BE6  Unknown               Unknown  Unknown
    a.out              00000000004036A3  MAIN__                      3  tb.f90
    a.out              0000000000403662  Unknown               Unknown  Unknown
    libc-2.12.so       000000381E01ED5D  __libc_start_main     Unknown  Unknown
    a.out              0000000000403569  Unknown               Unknown  Unknown
    

    Adding use of the module stops the SIGSEGV but the code terminates before printing Finish as documented:

    [ijb@login12(arcus-b) stack]$ cat tb2.f90
    ! testtrb.f90
    program testtrb
      Use ifcore, Only : tracebackqq
      Implicit None
      call tracebackqq()  ! This is for ifort
      !call backtrace()  ! This is for gfortran 
      print '(/1A/)', 'Finish.'
    end program testtrb
    [ijb@login12(arcus-b) stack]$ ifort -g -traceback tb2.f90
    [ijb@login12(arcus-b) stack]$ ./a.out
    Image              PC                Routine            Line        Source             
    a.out              0000000000406EFA  Unknown               Unknown  Unknown
    a.out              00000000004036CE  MAIN__                      5  tb2.f90
    a.out              0000000000403662  Unknown               Unknown  Unknown
    libc-2.12.so       000000381E01ED5D  __libc_start_main     Unknown  Unknown
    a.out              0000000000403569  Unknown               Unknown  Unknown
    

    Finally adding the non-default user_exit_code gives the desired behaviour

    [ijb@login12(arcus-b) stack]$ cat tb3.f90
    ! testtrb.f90
    program testtrb
      Use ifcore, Only : tracebackqq
      Implicit None
      call tracebackqq( user_exit_code = -1 )  ! This is for ifort
      !call backtrace()  ! This is for gfortran 
      print '(/1A/)', 'Finish.'
    end program testtrb
    [ijb@login12(arcus-b) stack]$ ifort -g -traceback tb3.f90
    [ijb@login12(arcus-b) stack]$ ./a.out
    Image              PC                Routine            Line        Source             
    a.out              0000000000406EFA  Unknown               Unknown  Unknown
    a.out              00000000004036CE  MAIN__                      5  tb3.f90
    a.out              0000000000403662  Unknown               Unknown  Unknown
    libc-2.12.so       000000381E01ED5D  __libc_start_main     Unknown  Unknown
    a.out              0000000000403569  Unknown               Unknown  Unknown
    
    Finish.