【问题标题】:Change variable value when signal is trapped in Fortran在 Fortran 中捕获信号时更改变量值
【发布时间】:2017-08-29 15:03:13
【问题描述】:

在 Fortran 上开发使用一些迭代过程的程序时,我不得不手动停止迭代(在不终止程序的情况下退出迭代循环)。

我决定向进程发送信号。我选择了 SIGALRM。我已经检查过它可以被困住而不会产生任何意想不到的后果。

当接收到信号时,改变标志值。该标志在迭代循环内被检查,如果标志为真则退出。此类代码示例如下。

!file mymod.f90
module mymod
use ifport
integer*4            :: err
integer*4            :: SIGNSET
integer*4, parameter :: mySignal=14
logical*1            :: toStopIteration

contains
!   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !
    integer*4 function setTrap() result(ret)
    implicit none

    call PXFSTRUCTCREATE('sigset',SIGNSET,err)
    call PXFSIGADDSET(SIGNSET,mySignal,err) !add my signal to the set.

    ret=0; return
    end function setTrap
!   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !
    integer*4 function onTrap(sig_num) result(rcode)
    implicit none
    integer*4 :: sig_num,err

    rcode=0
    select case (sig_num)
        case(mySignal)
            write (*,*) 'Signal occurred. Stop iteration called'
            write (*,*) 'flag: ',toStopIteration
            toStopIteration=.true.
            write (*,*) 'flag: ',toStopIteration
            rcode=1
            return
        case (SIGINT) ; stop
        case (SIGTERM); stop
        case (SIGABRT); stop
    end select

    end function onTrap
!   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !
end module mymod

!file main.f90
program main
use mymod
implicit none
integer*4 :: i,j,N,Niters,sum1

err=setTrap()
err=signal(mySignal, onTrap, -1)

toStopIteration=.false.

open (1,file='output')
write (*,*) 'PID=',getpid()
write (1,*) 'Outside',toStopIteration

N=5000000; Niters=100000

do i = 1,Niters
    if (toStopIteration) then
        toStopIteration=.false.
        exit
    endif

    sum1=0
    do j = 1,N
        sum1=sum1+j
    enddo
    write (1,*) i,toStopIteration,sum1
enddo

write (*,*) 'Procedure was terminated due to signal received. The last iteration was', i
write (*,*) 'Now I will do other job for you.'

stop
end program main

应用程序是使用 ifort 编译的:ifort -c -O2 -traceback。 当我向进程kill -14 pid发送信号时, 我得到了终端的输出:

 Signal occurred. Stop iteration called
 flag:  F
 flag:  T

但迭代循环仍在运行,如文件中所写,变量“toStopIteration”等于 false。

无意中,我发现使用-O0 -traceback 参数编译时,它工作正常。 为什么会发生?变量“toStopIteration”是否会成为具有这种优化级别的本地变量?我该怎么做才能让它正常工作?

提前致谢。 MuKeP。

【问题讨论】:

  • 对于所有人,谁会发现这个问题并需要详细信息。您需要使用logical*1, volatile :: toStopIteration 语句。但正如我正确理解的那样,它是 2003 年 Fortran 标准中出现的一个特性。

标签: fortran signals


【解决方案1】:

正如 Lorri 回答的那样(不幸的是,这个简洁但正确的答案已被误导性评论删除) - 尝试 toStopIteration 上的 volatile 属性。这告诉编译器该变量可能被其他东西重新定义,否则从编译器可见的源看来,该变量的值在迭代中无法更改,因此每次迭代都没有必要对其进行测试。

【讨论】:

  • 非常感谢您的帮助。它解决了我的问题。也许对我来说更准确地阅读规范会更好:)。
猜你喜欢
  • 2021-10-19
  • 2019-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多