Fortran对睡眠的调用不会阻止程序

Fortran对睡眠的调用不会阻止程序,fortran,gfortran,windows-subsystem-for-linux,Fortran,Gfortran,Windows Subsystem For Linux,我有最基本的Fortran程序: program sleep print*, "Sleeping" call sleep(30) print*, "Done" end program sleep 我用gfortran sleep.f90(9.3.0版)编译了它。从我从文档中了解到,这个程序应该休眠30秒,也就是说,我应该期望看到“休眠”30秒后打印“完成”。这并没有发生:我看到两个print语句同时出现,这表明调用sleep(30

我有最基本的Fortran程序:

program sleep
    print*, "Sleeping"
    call sleep(30)
    print*, "Done"
end program sleep

我用
gfortran sleep.f90
(9.3.0版)编译了它。从我从文档中了解到,这个程序应该休眠30秒,也就是说,我应该期望看到“休眠”30秒后打印“完成”。这并没有发生:我看到两个print语句同时出现,这表明
调用sleep(30)
不会以任何方式阻止我的程序。做
呼叫睡眠(10000)
没有任何区别。我正在Linux的Windows子系统(WSL Ubuntu 20.04)上编译并运行此程序。

因此,通过@roygvib在评论中建议的解决方案组合,此问题得到了解决。主要问题是WSL(Ubuntu20.04)环境中的睡眠被破坏。第一步是将损坏的
/usr/bin/sleep
替换为:

然后,修改Fortran程序,对新的
睡眠
可执行文件进行
系统
调用:

program sleep
    print*, "Sleeping"
    call system("sleep 30")
    print*, "Done"
end program sleep

在WSL的下一次更新之前,这种黑客行为将不得不进行。

睡眠过程不属于Fortran标准的一部分,不可移植。以下是一个解决方案,它可能适用于具有任何符合标准的Fortran编译器的所有系统:

module sleep_mod

    use, intrinsic :: iso_fortran_env, only: IK => int64, RK => real64, output_unit
    implicit none

contains

    subroutine sleep(seconds)

        implicit none

        real(RK), intent(in) :: seconds ! sleep time
        integer(IK)          :: countOld, countNew, countMax
        real(RK)             :: countRate

        call system_clock( count=countOld, count_rate=countRate, count_max=countMax )
        if (countOld==-huge(0_IK) .or. nint(countRate)==0_IK .or. countMax==0_IK) then
            write(output_unit,"(A)") "Error occurred. There is no processor clock."
            error stop
        end if

        countRate = 1._RK / countRate
        do
            call system_clock( count=countNew )
            if (countNew==countMax) then
                write(output_unit,"(A)") "Error occurred. Maximum processor clock count reached."
                error stop
            end if
            if ( real(countNew-countOld,kind=RK) * countRate > seconds ) exit
            cycle
        end do

    end subroutine sleep

end module sleep_mod

program main
    use sleep_mod, only: output_unit, sleep, RK
    implicit none
    write(output_unit,"(A)") "Sleep for 5 second."
    call execute_command_line(" ") ! flush stdout
    call sleep(seconds = 5._RK)
    write(output_unit,"(A)") "Wake up."
end program main

您可以在此处在线测试:

您使用什么操作系统?试试
30000
甚至
30000000
,会发生什么事?@VladimirF我已经更新了我的问题相关@roygvib这个问题似乎与您链接的第一个问题有关(关于WSL上的睡眠)。我已将
/usr/bin/sleep
替换为,但不幸的是,这没有传播到我的代码中。Fortran是否在内部使用
/usr/bin/sleep
?我可以在Fortran中重载对
sleep
的调用吗?我认为Fortran不使用
/usr/bin/sleep
,而是使用一些特定于编译器的库例程。所以,要使用Python脚本,也许我们可以使用
调用系统(“sleep.py 7”)
等等?(其中
sleep.py
是一个Python脚本,如您的链接所示。)这似乎在我的mac上可以工作……在nanosleep中看起来是个问题(在可执行文件上使用strace)。在18.04,它等待并返回0,在20.04,它返回无效参数。区别在于,在18.04,它使用nanosleep,但在20.04,它使用clock_nanosleep。中讨论了时钟的纳秒睡眠问题。如果你回到WSL上的Ubuntu18.04,你原来的程序就可以运行了。
module sleep_mod

    use, intrinsic :: iso_fortran_env, only: IK => int64, RK => real64, output_unit
    implicit none

contains

    subroutine sleep(seconds)

        implicit none

        real(RK), intent(in) :: seconds ! sleep time
        integer(IK)          :: countOld, countNew, countMax
        real(RK)             :: countRate

        call system_clock( count=countOld, count_rate=countRate, count_max=countMax )
        if (countOld==-huge(0_IK) .or. nint(countRate)==0_IK .or. countMax==0_IK) then
            write(output_unit,"(A)") "Error occurred. There is no processor clock."
            error stop
        end if

        countRate = 1._RK / countRate
        do
            call system_clock( count=countNew )
            if (countNew==countMax) then
                write(output_unit,"(A)") "Error occurred. Maximum processor clock count reached."
                error stop
            end if
            if ( real(countNew-countOld,kind=RK) * countRate > seconds ) exit
            cycle
        end do

    end subroutine sleep

end module sleep_mod

program main
    use sleep_mod, only: output_unit, sleep, RK
    implicit none
    write(output_unit,"(A)") "Sleep for 5 second."
    call execute_command_line(" ") ! flush stdout
    call sleep(seconds = 5._RK)
    write(output_unit,"(A)") "Wake up."
end program main