[Info-vax] Timeout in a write using QUIW.

Arne Vajhøj arne at vajhoej.dk
Wed Jun 21 20:03:33 EDT 2023


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






More information about the Info-vax mailing list