[Info-vax] Timeout in a write using QUIW.
Jan-Erik Söderholm
jan-erik.soderholm at telia.com
Thu Jun 22 02:48:17 EDT 2023
Den 2023-06-22 kl. 02:03, skrev Arne Vajhøj:
> On 6/21/2023 5:39 PM, Jan-Erik Söderholm wrote:
>> Den 2023-06-21 kl. 23:17, skrev Arne Vajhøj:
>>> On 6/21/2023 4:45 PM, Jan-Erik Söderholm wrote:
>>>> I was hoping that one could add a timeout value just as in the
>>>> read case, but it doesn't look so. So I do not see how to get
>>>> out of the hanging call to QIOW. Maybe using QIO, and doing
>>>> some extra coding to check the I/O, I guess.
>>>>
>>>> So, is there a way to get out of this state, still using QIOW?
>>>
>>> Totally untested idea:
>>>
>>> SYS$SETIMR with an AST routine that calls SYS$CANCEL
>>
>> My thought was to just queue the I/O, wait a sec or two
>> using $WAIT and then check the IOSB. If not completed OK,
>> CANCEL and return an error to the application...
>
> That is always an option.
>
> Just for fun I tried writing some code.
>
> I tested with read, because it is easy to recreate timeout
> for read.
>
> First the standard IO$M_TIMED as baseline:
>
> program r
> implicit none
> include '($ssdef)'
> include '($iodef)'
> integer*1 buf(1)
> integer*2 chan, iosb(4)
> integer*4 stat, tmo
> integer*4 sys$assign, sys$qiow, sys$dassgn
> external sys$assign, sys$qiow, sys$dassgn
> stat = sys$assign('TT:', chan, , , )
> if(stat.ne.SS$_NORMAL) call ooops(stat)
> tmo = 10
> write(*,*) 'Press a key within ', tmo, ' seconds'
> stat = sys$qiow(, %val(chan), %val(IO$_READVBLK+IO$M_TIMED),
> + iosb, , ,
> + buf, %val(1), %val(tmo), , , )
> if(stat.eq.SS$_NORMAL.and.iosb(1).eq.SS$_TIMEOUT) then
> write(*,*) 'Arne you are too slow'
> goto 100
> end if
> if(stat.ne.SS$_NORMAL) call ooops(stat)
> if(iosb(1).ne.SS$_NORMAL) call ooops(iosb(1))
> write(*,*) 'You entered code: ', buf
> 100 stat = sys$dassgn(%val(chan))
> if(stat.ne.SS$_NORMAL) call ooops(stat)
> end
> c
> subroutine ooops(stat)
> implicit none
> integer*4 stat
> write(*,*) 'status = ', stat
> stop
> end
>
> Now an implementation of my idea:
>
> program r1
> implicit none
> include '($ssdef)'
> include '($iodef)'
> integer*1 buf(1)
> integer*2 chan, iosb(4)
> integer*4 stat, tmo
> integer*8 tmo2
> integer*4 sys$assign, sys$qiow, sys$dassgn
> external sys$assign, sys$qiow, sys$dassgn
> external done
> stat = sys$assign('TT:', chan, , , )
> if(stat.ne.SS$_NORMAL) call ooops(stat)
> tmo = 10
> write(*,*) 'Press a key within ', tmo, ' seconds'
> tmo2 = -tmo * 10000000
> call sys$setimr(, tmo2, done, chan, )
> stat = sys$qiow(, %val(chan), %val(IO$_READVBLK),
> + iosb, , ,
> + buf, %val(1), , , , )
> if(stat.eq.SS$_NORMAL.and.iosb(1).eq.SS$_ABORT) then
> write(*,*) 'Arne you are too slow'
> goto 100
> end if
> if(stat.ne.SS$_NORMAL) call ooops(stat)
> if(iosb(1).ne.SS$_NORMAL) call ooops(iosb(1))
> call sys$cantim(0, )
> write(*,*) 'You entered code: ', buf
> 100 stat = sys$dassgn(%val(chan))
> if(stat.ne.SS$_NORMAL) call ooops(stat)
> end
> c
> subroutine ooops(stat)
> implicit none
> integer*4 stat
> write(*,*) 'status = ', stat
> stop
> end
> c
> subroutine done(chan)
> implicit none
> integer*2 chan
> call sys$cancel(%val(chan))
> return
> end
>
> And then how I interpret your suggestion:
>
> program r2
> implicit none
> include '($ssdef)'
> include '($iodef)'
> integer*1 buf(1)
> integer*2 chan, iosb(4)
> integer*4 stat, tmo
> integer*8 tmo2
> integer*4 sys$assign, sys$qio, sys$dassgn
> external sys$assign, sys$qio, sys$dassgn
> external done
> stat = sys$assign('TT:', chan, , , )
> if(stat.ne.SS$_NORMAL) call ooops(stat)
> tmo = 10
> write(*,*) 'Press a key within ', tmo, ' seconds'
> stat = sys$qio(, %val(chan), %val(IO$_READVBLK),
> + iosb, done, ,
> + buf, %val(1), , , , )
> if(stat.ne.SS$_NORMAL) call ooops(stat)
> tmo2 = -tmo * 10000000
> call sys$schdwk(, , tmo2, )
> call sys$hiber()
> if(iosb(1).eq.0) then
> write(*,*) 'Arne you are too slow'
> goto 100
> end if
> if(iosb(1).ne.SS$_NORMAL) call ooops(iosb(1))
> write(*,*) 'You entered code: ', buf
> 100 stat = sys$dassgn(%val(chan))
> if(stat.ne.SS$_NORMAL) call ooops(stat)
> end
> c
> subroutine ooops(stat)
> implicit none
> integer*4 stat
> write(*,*) 'status = ', stat
> stop
> end
> c
> subroutine done
> implicit none
> call sys$wake(, )
> return
> end
>
> And sorry for doing it in Fortran. But it would have taken me
> way more time to do in Cobol. And translating from Fortran to
> Cobol is probably easier than from C to Cobol. So Fortran
> it is.
>
> Arne
>
>
>
Will check, but yes, it sounds as we are on the same track.
And our I/O routines are in C and called from Cobol. But yes,
as far as I know, one could also write it in pure Cobol. :-)
The benefit with your timer/ast based solution is of course that,
when everything works fine (as it does in most cases), there is
no added delay in the routine. AS I thought, there would always
be the same delay no matter if it works or not.
Most doc examples are in C, so that is probably why the I/O
routine was written in C (in 1993 in this case).
We'll have a discussion. Now, even with wired connections, there
can be cases with powered off printers and such, so a better
error handling could be good apart from the Wifi issues.
Jan-Erik.
More information about the Info-vax
mailing list