unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: M <maximedevos@telenet.be>
To: Tomas Volf <~@wolfsden.cz>,
	 "Jonas Hahnfeld via Developers list for Guile,the GNU
	extensibility library" <guile-devel@gnu.org>
Subject: RE: How to abort a read from a socket after some time?
Date: Mon, 22 Jan 2024 00:46:23 +0100	[thread overview]
Message-ID: <20240122004625.dbmQ2B0062FFpwy01bmQ2u@baptiste.telenet-ops.be> (raw)
In-Reply-To: <Za0_ly1K7l3RV1hJ@ws>

[-- Attachment #1: Type: text/plain, Size: 2254 bytes --]

(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

[-- Attachment #2: Type: text/html, Size: 4165 bytes --]

       reply	other threads:[~2024-01-21 23:46 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <Za0_ly1K7l3RV1hJ@ws>
2024-01-21 23:46 ` M [this message]
2024-01-22 11:38   ` How to abort a read from a socket after some time? Tomas Volf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240122004625.dbmQ2B0062FFpwy01bmQ2u@baptiste.telenet-ops.be \
    --to=maximedevos@telenet.be \
    --cc=guile-devel@gnu.org \
    --cc=~@wolfsden.cz \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).