Fortran 调用睡眠不会阻止程序

Fortran call to sleep does not block program

我有最基本的 Fortran 程序:

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

我用 gfortran sleep.f90(版本 9.3.0)编译。根据我从 sleep 文档中了解到的情况,该程序应该休眠 30 秒,即我应该期望在“休眠”30 秒后看到“完成”打印出来。这不会发生:我看到两个打印语句同时出现,表明 call sleep(30) 不会以任何方式阻止我的程序。做 call sleep(10000) 没有任何区别。我正在为 Linux (WSL Ubuntu 20.04) 在 Windows 子系统上编译和 运行 这个程序。

所以这个问题是通过@roygvib 在评论中建议的组合解决方案解决的。主要问题是 WSL (Ubuntu 20.04) 环境中的 sleep 已损坏。第一步是将损坏的 /usr/bin/sleep 替换为 this Python script:

#!/usr/bin/env python3

import sys
import time

time.sleep(int(sys.argv[1]))

然后,修改 Fortran 程序以 system 调用这个新的 sleep 可执行文件:

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

在 WSL 的下一次更新之前,必须执行此 hack。

sleep 过程不是 Fortran 标准和 non-portable 的一部分。这是一个可能适用于任何 standard-compliant 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

您可以在这里在线测试:https://www.tutorialspoint.com/compile_fortran_online.php