brown@wucs.UUCP.UUCP (11/07/86)
Problem:
FORTRAN analysis system with embedded command interpreter. Need to
be able to interrupt processing(computational and i/o) via a ctrl-c and
return to analysis system's command interpreter. This worked in
VMS v3 using the sys$unwind mechanism invoked from a condition handler.
This doesn't work in VMS v4.(I've tried it on 4.0-4.4, I don't know what
versions of the FORTRAN system were installed in all cases)
The FORTRAN run time library is apparently left in some bizarre state if
a read or write is interrupted. Any further i/o operation terminates the
program with some error (which varies depending on the operation).
Question:
Is there some function I can call which will cause the FORTRAN run
time library to restore itself to a consistent state?
Is this a bug or a feature?
I rarely work on VMS now and would appreciate any info or pointers
to documents which might show a way around this problem.
Regards,
Mike Brown Biomedical Computer Laboratory
Institute for Biomedical Computing
Washington University
700 S. Euclid Avenue
St. Louis, MO 63110
(314) 362-2135
arpa: brown%wucs.uucp@seismo.css.gov
uucp: {ihnp4,...}!wucs!brownHELLER%cs.umass.edu@RELAY.CS.NET (Stride 440 User) (11/14/86)
The problem is FORTRAN I/O is non-"atomic", that is a FORTRAN statement
like:
accept 10,x,y,x
does not generate a single call to some FOR$blah routine, but in fact
something like 5 calls to FOR$blah routines. This sequence is really a
"critical section" of sorts. At least for you purposes it is. If your ^C
handler bobs along in this critical section, you will end up with a pending
I/O operation on the unit number (-3 in the case of accept) associatiated
with the interupted I/O statement. The next I/O request on that unit number
can't be processed, and fails with a recursive I/O operation. That unit
number is now dead. The only thing you can do now is exit back to DCL and
start over. So much for FORTRAN I/O.
What you have to do is poll for ^C. Your ^C handler simply sets a logical
variable in a common block. This variable is tested at "reasonable" points
in the code, and a non-local exit is done at these points. (Probably by
doing a lib$signal with some made up signal which is caught by your
condition handler, which does a sys$unwind.
There is a routine called FOR$IO_END (something like that), but you can only
call this if there is an I/O operation in progress AND if you know the unit
# of the pending I/O. There is no universal "clean up any I/O, if any" type
function. Once a unit has been bashed with a "Recursive I/O operation", it
is completely dead, with no recovery posible. The only safe thing you can do
is the ^C polling method. Also, if you setup an out-of-band AST (like DCL's
^T) to report status, DON'T do FORTRAN I/O in it, use SYS$QIOW only, using
SYS$FAO(L) or C's sprintf, not FORTRAN's ENCODE to format the message
buffer(s).
Robert Heller
ARPANet: Heller@UMass-CS.CSNET
BITNET: Heller@UMass.BITNET
BIX: Heller
GEnie: RHeller
FidoNet: 101/27 (Dave's Fido, Gardner MA)