guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: How to abort a read from a socket after some time?


From: M
Subject: RE: How to abort a read from a socket after some time?
Date: Mon, 22 Jan 2024 00:46:23 +0100

(Please ignore the wrong To: field, e-mail program is being silly)

 

>I am trying to figure out how to abort a read from a socket after some time elapses.  >I failed to figure out how to do so.

> 

> All code below runs after handler is set:

> 

>    (sigaction SIGALRM (lambda _ (display "Alarm!\n")))

 

Assuming the read-char takes too long, the kernel sends a SIGALRM to Guile. Hence, the C signal handler is run (which sets some fields somewhere indicating that this handler should be run later in the sense of system-async-mark), and the syscall behind read-char returns EINTR.

 

As this is a fake error (passing it on as a Scheme exception would result in rather messy semantics, e.g. consider the case where things are interrupted twice in a row, time such that the exception handler itself is interrupted with a new exception), Guile decides to retry the syscall, but before that, it checks if there is a system-async-mark to be done, so it does that thing – i.e., it displays “Alarm!\n” and merrily continue on reading a character.

 

Now, going by the rest of the mail, it appears you don’t just want to print a message, you want to _abort_. So you should modify your handlers to abort, i.e., call an escape continuation.

 

(define escaper (make-parameter #false)

(sigaction SIGALRM (lambda _ (let ((e (escaper))) (if e (e)))))

[set up sockets, etc.]

;; returns char on success, #false on timeout.

(define (read-char-or-timeout)

  (let/ec e

    [set up an alarm]

    (parameterize ((escaper (lambda () (e #false))))

      (read-char e)))) ; XXX add port argument, maybe stop the alarm afterwards?

 

(This assumes the signal handler is run in the same thread as the thread using read-char-or-timeout, I don’t know if this is the case.)

 

This code has a bug, however: it might be the case that the signal is received right after read-char finishes but before the parameterize ends. In that case, the character is lost and read-char-or-timeout reports a “timeout”, losing the character, which is most likely undesired.

 

So, if you do things like this, I think you should modify the signal handler to instead set a a-timeout-happened flag, and let read-char-or-timeout read that flag.

 

Best regards,

Maxime Devos


reply via email to

[Prev in Thread] Current Thread [Next in Thread]