Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions ac/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,24 @@ AC_CONFIG_COMMANDS(Makefile.dep, [make depend])

# POSIX verification tests

# These symbols may be defined as macros, making them inaccessible by Fortran.
# These three exist in modern BSD and Linux libc, so we just confirm them.
# But one day, we many need to handle them more carefully.
AX_FC_CHECK_BIND_C([setjmp], [], [AC_MSG_ERROR([Could not find setjmp.])])
AX_FC_CHECK_BIND_C([longjmp], [], [AC_MSG_ERROR([Could not find longjmp.])])
AX_FC_CHECK_BIND_C([siglongjmp], [], [AC_MSG_ERROR([Could not find siglongjmp.])])
# Symbols in <setjmp.h> may be defined as macros, making them inaccessible by
# Fortran C bindings. `sigsetjmp` is known to have an internal symbol in
# glibc, so we check for this possibility. For the others, we only check for
# existence.

# If the need arises, we may want to define these under a standalone macro.

# Validate the setjmp symbol
AX_FC_CHECK_BIND_C([setjmp],
[SETJMP="setjmp"], [SETJMP="setjmp_missing"]
)
AC_DEFINE_UNQUOTED([SETJMP_NAME], ["${SETJMP}"])

# Validate the longjmp symbol
AX_FC_CHECK_BIND_C([longjmp],
[LONGJMP="longjmp"], [LONGJMP="longjmp_missing"]
)
AC_DEFINE_UNQUOTED([LONGJMP_NAME], ["${LONGJMP}"])

# Determine the sigsetjmp symbol. If missing, then point to sigsetjmp_missing.
#
Expand All @@ -263,6 +275,13 @@ for sigsetjmp_fn in sigsetjmp __sigsetjmp; do
done
AC_DEFINE_UNQUOTED([SIGSETJMP_NAME], ["${SIGSETJMP}"])

# Validate the siglongjmp symbol
AX_FC_CHECK_BIND_C([siglongjmp],
[SIGLONGJMP="siglongjmp"], [SETJMP="siglongjmp_missing"]
)
AC_DEFINE_UNQUOTED([SIGLONGJMP_NAME], ["${SIGLONGJMP}"])


# Verify the size of nonlocal jump buffer structs
# NOTE: This requires C compiler, but can it be done with a Fortran compiler?
AC_LANG_PUSH([C])
Expand Down
51 changes: 44 additions & 7 deletions src/framework/posix.F90
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ function sleep_posix(seconds) result(rc) bind(c, name="sleep")
!! returns 0. When `longjmp` is later called, the program is restored to the
!! point where `setjmp` was called, except it now returns a value (rc) as
!! specified by `longjmp`.
function setjmp(env) result(rc) bind(c, name="setjmp")
function setjmp(env) result(rc) bind(c, name=SETJMP_NAME)
! #include <setjmp.h>
! int setjmp(jmp_buf env);
import :: jmp_buf, c_int
Expand Down Expand Up @@ -175,7 +175,7 @@ end function sigsetjmp

!> C interface to POSIX longjmp()
!! Users should use the Fortran-defined longjmp() function.
subroutine longjmp_posix(env, val) bind(c, name="longjmp")
subroutine longjmp_posix(env, val) bind(c, name=LONGJMP_NAME)
! #include <setjmp.h>
! int longjmp(jmp_buf env, int val);
import :: jmp_buf, c_int
Expand All @@ -188,7 +188,7 @@ end subroutine longjmp_posix

!> C interface to POSIX siglongjmp()
!! Users should use the Fortran-defined siglongjmp() function.
subroutine siglongjmp_posix(env, val) bind(c, name="siglongjmp")
subroutine siglongjmp_posix(env, val) bind(c, name=SIGLONGJMP_NAME)
! #include <setjmp.h>
! int siglongjmp(jmp_buf env, int val);
import :: sigjmp_buf, c_int
Expand Down Expand Up @@ -344,11 +344,36 @@ subroutine siglongjmp(env, val)
call siglongjmp_posix(env, val_c)
end subroutine siglongjmp


! Symbols in <setjmp.h> may be platform-dependent and may not exist if defined
! as a macro. The following functions permit compilation when they are
! unavailable, and report a runtime error if used in the program.

!> Placeholder function for a missing or unconfigured setjmp
function setjmp_missing(env) result(rc) bind(c)
type(jmp_buf), intent(in) :: env
!< Current process state (unused)
integer(kind=c_int) :: rc
!< Function return code (unused)

print '(a)', 'ERROR: setjmp() is not implemented in this build.'
print '(a)', 'Recompile with autoconf or -DSETJMP_NAME=\"<symbol name>\".'
error stop
end function setjmp_missing

!> Placeholder function for a missing or unconfigured longjmp
subroutine longjmp_missing(env, val) bind(c)
type(jmp_buf), intent(in) :: env
!< Current process state (unused)
integer(kind=c_int), value, intent(in) :: val
!< Enable signal state flag (unused)

print '(a)', 'ERROR: longjmp() is not implemented in this build.'
print '(a)', 'Recompile with autoconf or -DLONGJMP_NAME=\"<symbol name>\".'
error stop
end subroutine longjmp_missing

!> Placeholder function for a missing or unconfigured sigsetjmp
!!
!! The symbol for sigsetjmp can be platform-dependent and may not exist if
!! defined as a macro. This function allows compilation, and reports a runtime
!! error if used in the program.
function sigsetjmp_missing(env, savesigs) result(rc) bind(c)
type(sigjmp_buf), intent(in) :: env
!< Current process state (unused)
Expand All @@ -365,4 +390,16 @@ function sigsetjmp_missing(env, savesigs) result(rc) bind(c)
rc = -1
end function sigsetjmp_missing

!> Placeholder function for a missing or unconfigured siglongjmp
subroutine siglongjmp_missing(env, val) bind(c)
type(sigjmp_buf), intent(in) :: env
!< Current process state (unused)
integer(kind=c_int), value, intent(in) :: val
!< Enable signal state flag (unused)

print '(a)', 'ERROR: siglongjmp() is not implemented in this build.'
print '(a)', 'Recompile with autoconf or -DSIGLONGJMP_NAME=\"<symbol name>\".'
error stop
end subroutine siglongjmp_missing

end module posix
16 changes: 14 additions & 2 deletions src/framework/posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,24 @@
#define SIZEOF_SIGJMP_BUF SIZEOF_JMP_BUF
#endif

! glibc defines sigsetjmp as __sigsetjmp via macro readable from <setjmp.h>.
! Wrappers to <setjmp.h> are disabled on default.
#ifndef SETJMP_NAME
#define SETJMP_NAME "setjmp_missing"
#endif

#ifndef LONGJMP_NAME
#define LONGJMP_NAME "longjmp_missing"
#endif

#ifndef SIGSETJMP_NAME
#define SIGSETJMP_NAME "sigsetjmp_missing"
#endif

! This should be defined by /usr/include/signal.h
#ifndef SIGLONGJMP_NAME
#define SIGLONGJMP_NAME "siglongjmp_missing"
#endif

! This should be defined by <signal.h>;
! If unset, we use the most common (x86) value
#ifndef POSIX_SIGUSR1
#define POSIX_SIGUSR1 10
Expand Down