- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I'm working on old code that was originally only built as a 32-bit version. This code uses the setjmp/longjmp routines to easily break out of a location that may be deep inside the call sequence. Originally a simple STOP statement was used, but when the code was turned into a DLL, it was the easiest way to quit the DLL. It works perfectly in a 32-bit setup, but when I try to test this feature with a 64-bit DLL, I couldn't get it to work. Every time I try to call the longjmp routine an exception is thrown somewhere in ntdll.dll. The jmp_buf object seems to match the one defined in the setjmp.h source file, which is different between the 32-bit and 64-bit versions.
Is there something more to do for 64-bit or it just doesn't work in 64-bit?
Regards,
P.S.: Here is my source code:
use IFWIN, only: UINT64
!dec$ if defined(_X86_)
integer(4), public :: JMP_BUF(16)
!dec$ else
type SETJMP_FLOAT128
sequence
integer(UINT64) Part(2)
end type SETJMP_FLOAT128
type(SETJMP_FLOAT128), public :: JMP_BUF(16)
!dec$ endif
!dec$ if defined(_X86_)
interface
integer(4) function SETJMP(JMP_BUF)
!dec$ attributes C, alias:'__setjmp' :: SETJMP
integer(4) :: JMP_BUF(*)
end function
end interface
interface
subroutine LONGJMP(JMP_BUF, RET_VALUE)
!dec$ attributes C :: LONGJMP
integer(4) :: JMP_BUF(*)
integer(4) :: RET_VALUE
end subroutine
end interface
!dec$ else
interface
integer(4) function SETJMP(JMP_BUF)
!dec$ attributes C :: SETJMP
import
type(SETJMP_FLOAT128) :: JMP_BUF(*)
end function
end interface
interface
subroutine LONGJMP(JMP_BUF, RET_VALUE)
!dec$ attributes C :: LONGJMP
import
type(SETJMP_FLOAT128) :: JMP_BUF(*)
integer(4) :: RET_VALUE
end subroutine
end interface
!dec$ endif
Link Copied
- « Previous
-
- 1
- 2
- Next »
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am not sure to understand what you mean by:
"You will (should) find that the allocation was not returned"
Did you meant, passing an allocatable array to the subroutine that performs the longjmp call, and allocating the corresponding dummy argument in that routine before the call to longjmp()?
About the files that may be not closed before the call to longjmp(), the routine that handle the longjmp call makes sure to close these files, and if no, the calling process, on return with such an error condition, calls another entry point that performs the desired closes.
Phil.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>Did you meant, passing an allocatable array to the subroutine that performs the longjmp call, and allocating the corresponding dummy argument in that routine before the call to longjmp()?
No, I though I was clear.
DLL "main" sets return for long jump, DLL main calls subroutine FOO, subroutine FOO has local (not dummy) allocatable array, FOO allocates array, FOO issues longjmp before deallocating array, DLL main returns allocation of that array still allocated (iow memory leak). Array will not be deallocated if there isn't a mechanism such as that on normal return.
Note, in stepping through the x64 dissassembly code of the longjmp, it appeared as if there is an IVF shell function construction that was attempting to return through the normal RETURN cleanup code, which seemed to be caught in an endless loop (I quit after stepping in the debugger after several iterations). As to if this code is a broken attempt at (longjmp) exception handling I cannot say for sure, but it suspiciously looks like it is as the non-shell C longjmp will simply restore the SP, PC and pass error code. If you step into the disassembly code at line 23 (longjmp) you can see that a shell function is used and that it iterates in a much more complicated manner (which I suspect is broken code).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jim,
Thanks for the clarification. I didn't plan any call to longjmp() without deallocating all arrays locally allocated so I was confused with your answer, but I agree that all allocated array not deallocated before the longmp() call will lead to memory leaks. Normally, even if deallocation is automatically done by the compiler for non-SAVED arrays on subroutine exit, I prefer to deallocate them manually before exiting my subroutines/functions.
Phil.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>I didn't plan any call to longjmp() without deallocating all arrays locally allocated so I was confused with your answer,
Consider:
function entry
...
setjmp(...)
call FEE(..)
subroutine FEE(...)
...
allocate(localArrayA(n))
call FI(...)
subroutine FI(...)
...
allocate(localArrayB(n))
...
if(error) then
delete(localArrayB)
longjmp(...) ! ukp-level localArrayA still allocated
endif
...
Unless your code is (and will always be) one level deep from point of longjmp, your local error handling (performing the deletes) will not perform (potential) up-level deletes. What you need then, is what amounts to your own analog (Fortran compliant) "try/catch".
I would suggest starting with IanH's shell functions, modified to permit stacking try-levels. I will leave it an exercise for you to write the code to implement the usage such as:
subroutine FOO(...)
...
use trycatch
type(try_t) :: try ! link's to upper-level try's
...
do
if(try%begin()) then
... ! protected code
allocate(A(n))
...
else
... ! cleanup
delete(A)
if(catch_code_fatal_expr) call try%throw(catch_code_fatal) ! pop's level
... ! retry code
cycle ! attempt recovery
endif
... ! unprotected code
end do
...
return ! effectively pop's try
end subroutine FOO
This should not be all that hard to write (incorporating the exception handling into your code is a different story).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jim,
I fully agree with your comments, and I will try to play a bit around with your code suggestion (and Ian code sample).
Thanks.
Phil.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page
- « Previous
-
- 1
- 2
- Next »