Skip to content

Commit

Permalink
Use POSIX stat to check if restart dir exists
Browse files Browse the repository at this point in the history
Using inquire() to check for directory existence is not possible, since
at least one compiler (Intel) does not consider directories to be files.

The inquire call is replaced with a C interface to the POSIX stat()
function.  We do not fully emulate the behavior of stat, but we use its
return value to determine existence of directories.  This provides a
more reliable method for identifying the existence of the directory.

This should resolve many of the observed problems with RESTART creation
in coupled runs.
  • Loading branch information
marshallward committed Jul 29, 2023
1 parent 3d9190c commit 5efad9b
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 3 deletions.
6 changes: 4 additions & 2 deletions src/framework/MOM_get_input.F90
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module MOM_get_input
use MOM_file_parser, only : open_param_file, param_file_type
use MOM_io, only : file_exists, close_file, slasher, ensembler
use MOM_io, only : open_namelist_file, check_nml_error
use posix, only : mkdir
use posix, only : mkdir, stat, stat_buf

implicit none ; private

Expand Down Expand Up @@ -55,6 +55,8 @@ subroutine get_MOM_input(param_file, dirs, check_params, default_input_filename,
character(len=240) :: output_dir
integer :: unit, io, ierr, valid_param_files

type(stat_buf) :: buf

namelist /MOM_input_nml/ output_directory, input_filename, parameter_filename, &
restart_input_dir, restart_output_dir

Expand Down Expand Up @@ -97,7 +99,7 @@ subroutine get_MOM_input(param_file, dirs, check_params, default_input_filename,

! Create the RESTART directory if absent
if (is_root_PE()) then
if (.not. file_exists(dirs%restart_output_dir)) then
if (stat(trim(dirs%restart_output_dir), buf) == -1) then
ierr = mkdir(trim(dirs%restart_output_dir), int(o'700'))
if (ierr == -1) &
call MOM_error(FATAL, 'Restart directory could not be created.')
Expand Down
49 changes: 48 additions & 1 deletion src/framework/posix.F90
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ module posix

implicit none

!> Container for file metadata from stat
!!
!! NOTE: This is currently just a placeholder containing fields, such as size,
!! uid, mode, etc. A readable Fortran type may be used in the future.
type, bind(c) :: stat_buf
private
character(kind=c_char) :: state(SIZEOF_STAT_BUF)
!< Byte array containing file metadata
end type stat_buf

!> Container for the jump point buffer created by setjmp().
!!
!! The buffer typically contains the current register values, stack pointers,
Expand Down Expand Up @@ -67,6 +77,19 @@ function mkdir_posix(path, mode) result(rc) bind(c, name="mkdir")
!< Function return code
end function mkdir_posix

!> C interface to POSIX stat()
!! Users should use the Fortran-defined stat() function.
function stat_posix(path, buf) result(rc) bind(c, name="stat")
import :: c_char, stat_buf, c_int

character(kind=c_char), dimension(*), intent(in) :: path
!< Pathname of a POSIX file
type(stat_buf), intent(in) :: buf
!< Information describing the file if it exists
integer(kind=c_int) :: rc
!< Function return code
end function

!> C interface to POSIX signal()
!! Users should use the Fortran-defined signal() function.
function signal_posix(sig, func) result(handle) bind(c, name="signal")
Expand Down Expand Up @@ -272,6 +295,27 @@ function mkdir(path, mode) result(rc)
rc = int(rc_c)
end function mkdir

!> Get file status
!!
!! This obtains information about the named file and writes it to buf.
!! If found, it returns zero. Otherwise, it returns -1.
function stat(path, buf) result(rc)
character(len=*), intent(in) :: path
!< Pathname of file to be inspected
type(stat_buf), intent(out) :: buf
!< Buffer containing information about the file if it exists
! NOTE: Currently the contents of buf are not readable, but we could move
! the contents into a readable Fortran type.
integer :: rc
!< Function return code

integer(kind=c_int) :: rc_c

rc_c = stat_posix(path//c_null_char, buf)

rc = int(rc_c)
end function stat

!> Create a signal handler `handle` to be called when `sig` is detected.
!!
!! If successful, the previous handler for `sig` is returned. Otherwise,
Expand Down Expand Up @@ -391,6 +435,9 @@ function setjmp_missing(env) result(rc) bind(c)
print '(a)', 'ERROR: setjmp() is not implemented in this build.'
print '(a)', 'Recompile with autoconf or -DSETJMP_NAME=\"<symbol name>\".'
error stop

! NOTE: compilers may expect a return value, even if it is unreachable
rc = -1
end function setjmp_missing

!> Placeholder function for a missing or unconfigured longjmp
Expand Down Expand Up @@ -418,7 +465,7 @@ function sigsetjmp_missing(env, savesigs) result(rc) bind(c)
print '(a)', 'Recompile with autoconf or -DSIGSETJMP_NAME=\"<symbol name>\".'
error stop

! NOTE: Compilers may expect a return value, even if it is unreachable
! NOTE: compilers may expect a return value, even if it is unreachable
rc = -1
end function sigsetjmp_missing

Expand Down
6 changes: 6 additions & 0 deletions src/framework/posix.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
#ifndef MOM6_POSIX_H_
#define MOM6_POSIX_H_

! STAT_BUF_SIZE should be set to sizeof(stat).
! The default value is based on glibc 2.28.
#ifndef SIZEOF_STAT_BUF
#define SIZEOF_STAT_BUF 144
#endif

! JMP_BUF_SIZE should be set to sizeof(jmp_buf).
! If unset, then use a typical glibc value (25 long ints)
#ifndef SIZEOF_JMP_BUF
Expand Down

0 comments on commit 5efad9b

Please sign in to comment.