2017-08-29 14 views
2

Fortranでプログラムを開発する際に、いくつかの反復プロシージャを使用するため、反復を手動で停止する必要がありました(プログラム終了なしで反復ループを終了する必要があります)。信号がFortranでトラップされたときに変数値を変更する

私はプロセスに信号を送信することにしました。私はSIGALRMを選んだ。私はそれが予期せぬ結果なしに閉じ込めることができることを確認しました。

受信信号を受信すると、フラグの値が変更されます。このフラグは繰り返しループ内でチェックされ、flagがtrueの場合は終了します。そのようなコードのサンプルを以下に示します。

!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は」偽等しいです。

-O0 -tracebackパラメータでコンパイルすると、うまく動作することがわかりました。 どうしてですか?このような最適化レベルでは、変数 "toStopIteration"はローカルになりますか?それを正しく動作させるために何ができるのですか?

ありがとうございます。 MuKeP。

+0

詳細については、この質問をご覧ください。 'logical * 1、volatile :: toStopIteration'文を使う必要があります。しかし、私が正しく理解したように、それは2003年のFortran標準に登場した機能です。 – MuKeP

答えて

2

Lorriは答えました(残念ながら、簡潔ではありますが、間違ったレビューによって誤解が削除されました)。 - toStopIterationのvolatile属性を試してください。これは、変数が別のものによって再定義される可能性があることをコンパイラに指示します。そうでなければ、コンパイラに表示されるソースから、その変数の値が反復で変更できないように見えます。

+0

ありがとうございました。それは私の問題を解決しました。たぶん私は仕様をより正確に読む方が良いでしょう。 – MuKeP

関連する問題