• Interrupted system call on read after ~20 minutes inactivity?

    From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.misc,comp.lang.c on Sat Oct 4 00:59:43 2025
    From Newsgroup: comp.lang.misc

    I'm not sure where this effect originated from; whether from the
    "host language" (Algol 68/Genie), the underlying implementation
    language ("C", libc), or from the OS (Linux) or the distribution
    setup. - Maybe someone has an idea what's going on here...?

    In context of a Genie (Algol 68) program, after leaving the
    terminal some minutes while the program was waiting in a 'read',
    the program terminated by an interrupt. So I set up this simple
    call to reproduce it... - it gets interrupted after ~21 minutes
    of inactivity.


    $ date ; genie -x 'read (newline)' ; date
    Fr., 03. Oktober 2025, 16:09:29 (CEST)
    1 (read (newline))
    1
    a68g: runtime error: 1: error transputting PROC (REF FILE) VOID value, interrupted system call, in VOID
    closed-clause starting at "(" in this line.
    Fr., 03. Oktober 2025, 16:30:59 (CEST)


    The maintainer of the Genie system told me that he has no such
    logic implemented in his tool, and he suspected the libc as the
    source of the interrupted system call.

    Has anyone observed such behavior (maybe in similar contexts,
    when waiting for input, where no own interrupt timer has been
    set up)?

    Thanks.

    Janis
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.misc,comp.lang.c on Fri Oct 3 23:31:18 2025
    From Newsgroup: comp.lang.misc

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    I'm not sure where this effect originated from; whether from the
    "host language" (Algol 68/Genie), the underlying implementation
    language ("C", libc), or from the OS (Linux) or the distribution
    setup. - Maybe someone has an idea what's going on here...?

    In context of a Genie (Algol 68) program, after leaving the
    terminal some minutes while the program was waiting in a 'read',
    the program terminated by an interrupt. So I set up this simple
    call to reproduce it... - it gets interrupted after ~21 minutes
    of inactivity.


    $ date ; genie -x 'read (newline)' ; date
    Fr., 03. Oktober 2025, 16:09:29 (CEST)
    1 (read (newline))
    1
    a68g: runtime error: 1: error transputting PROC (REF FILE) VOID value, >interrupted system call, in VOID
    closed-clause starting at "(" in this line.
    Fr., 03. Oktober 2025, 16:30:59 (CEST)


    The maintainer of the Genie system told me that he has no such
    logic implemented in his tool, and he suspected the libc as the
    source of the interrupted system call.

    run the application under strace to see the system call that was
    interrupted.

    $ strace -f -o syscall.tr genie -x 'read (newline)'
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Alan Bawden@alan@csail.mit.edu to comp.lang.misc,comp.lang.c on Fri Oct 3 19:33:13 2025
    From Newsgroup: comp.lang.misc

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    The maintainer of the Genie system told me that he has no such
    logic implemented in his tool, and he suspected the libc as the
    source of the interrupted system call.

    Under Unix, pretty much _any_ call to read() needs to be prepared to
    handle an EINTR. Often all you do is just loop back and call read()
    again. It isn't libc's job to handle this for you -- you must handle it yourself.

    So in your case either the _runtime_ should be handling this for you, or
    it is something that the runtime expect _you_ to handle.
    --
    Alan Bawden
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.misc on Fri Oct 3 23:54:16 2025
    From Newsgroup: comp.lang.misc

    On Fri, 03 Oct 2025 19:33:13 -0400, Alan Bawden wrote:

    Under Unix, pretty much _any_ call to read() needs to be prepared to
    handle an EINTR. Often all you do is just loop back and call read()
    again.

    Just a note, yourCOll only get that error if nothing is read. Otherwise
    the call will terminate with no error, and return the usual indication
    of the number of bytes read.

    If thatrCOs less than you were expecting, then you keep that data and
    retry the read to get more.

    It isn't libc's job to handle this for you -- you must handle it
    yourself.

    I guess the rationale for this is you might want to take some other
    action before, or instead of, retrying the read.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.misc,comp.lang.c on Sat Oct 4 01:57:20 2025
    From Newsgroup: comp.lang.misc

    On 04.10.2025 01:31, Scott Lurndal wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    [...]

    run the application under strace to see the system call that was
    interrupted.

    $ strace -f -o syscall.tr genie -x 'read (newline)'

    I did that already but couldn't take anything from it that would
    enlighten me... :-/

    ...
    seek(10, 27, SEEK_SET) = 27
    rt_sigprocmask(SIG_BLOCK, [HUP INT QUIT PIPE], [], 8) = 0
    vfork() = 18272
    rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
    rt_sigaction(SIGINT, {0x41a980, [], SA_RESTORER|SA_INTERRUPT,
    0x7f536ec060b0}, {SIG_DFL, [], 0}, 8) = 0
    wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 1}], WSTOPPED|WCONTINUED,
    NULL) = 18272
    --- SIGCHLD (Child exited) @ 0 (0) ---
    rt_sigreturn(0x11) = 18272
    wait4(-1, 0x7ffd554fda0c, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD
    (No child processes)
    wait4(-1, 0x7ffd554fda0c, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD
    (No child processes)
    rt_sigaction(SIGCHLD, {0x428250, [], SA_RESTORER|SA_INTERRUPT,
    0x7f536ec060b0}, {0x428250, [], SA_RESTORER|SA_INTERRUPT,
    0x7f536ec060b0}, 8) = 0
    ioctl(2, TIOCGPGRP, [18270]) = 0
    lseek(10, 325, SEEK_SET) = 325
    lseek(10, 33, SEEK_SET) = 33
    fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 63), ...}) = 0
    fstat(2, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 63), ...}) = 0 exit_group(1) = ?


    ...I suppose I would need to be familiar with the Genie source code
    to understand where what happens. Or can there already be seen what's
    going on?

    Janis

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.misc on Sat Oct 4 02:00:36 2025
    From Newsgroup: comp.lang.misc

    On 04.10.2025 01:33, Alan Bawden wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    The maintainer of the Genie system told me that he has no such
    logic implemented in his tool, and he suspected the libc as the
    source of the interrupted system call.

    Under Unix, pretty much _any_ call to read() needs to be prepared to
    handle an EINTR. Often all you do is just loop back and call read()
    again. It isn't libc's job to handle this for you -- you must handle it yourself.

    Yeah, that would also be my expectation.

    So in your case either the _runtime_ should be handling this for you, or
    it is something that the runtime expect _you_ to handle.

    Usually if I want timed interrupts I set that up explicitly or use
    an existing feature or option. But here - in the one-liner - there's
    nothing I had done, and Genie's 'read' is also not configurable to
    support timeouts.

    Hmm..

    Janis

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From richard@richard@cogsci.ed.ac.uk (Richard Tobin) to comp.lang.misc,comp.lang.c on Sat Oct 4 00:18:31 2025
    From Newsgroup: comp.lang.misc

    In article <10bpkh1$25arg$1@dont-email.me>,
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    In context of a Genie (Algol 68) program, after leaving the
    terminal some minutes while the program was waiting in a 'read',
    the program terminated by an interrupt. So I set up this simple
    call to reproduce it... - it gets interrupted after ~21 minutes
    of inactivity.

    [...]

    The maintainer of the Genie system told me that he has no such
    logic implemented in his tool

    The maintainer is mistaken.

    If you look in a68g-io.c you will see that the function io_read_conv()
    returns -1 if read() returns EINTR more than MAX_RESTART+1 (257) times.

    If you look in a68-bits.c you will see that setitimer() is called with
    an interval of INTERRUPT_INTERVAL (5) seconds at the start and is
    called again whenever the handler gets run.

    Your read therefore fails after 258*5 = 1290 seconds.

    (The intention of all this seems to be a to implement a cpu time
    limit, but it also has this presumably undesired effect.)

    On a system where read() is automatically restarted after SIGALRM
    is handled, none of this will happen.

    -- Richard
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Alan Bawden@alan@csail.mit.edu to comp.lang.misc on Fri Oct 3 20:26:19 2025
    From Newsgroup: comp.lang.misc

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    Usually if I want timed interrupts I set that up explicitly or use
    an existing feature or option. But here - in the one-liner - there's
    nothing I had done, and Genie's 'read' is also not configurable to
    support timeouts.

    It's not necessarily a timeout. Maybe something else in the system sets
    up an interrupt handler for some other reason. EINTR happens. Be prepared.
    --
    Alan Bawden
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.misc,comp.lang.c on Sat Oct 4 02:27:57 2025
    From Newsgroup: comp.lang.misc

    On 04.10.2025 02:18, Richard Tobin wrote:
    In article <10bpkh1$25arg$1@dont-email.me>,
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    In context of a Genie (Algol 68) program, after leaving the
    terminal some minutes while the program was waiting in a 'read',
    the program terminated by an interrupt. So I set up this simple
    call to reproduce it... - it gets interrupted after ~21 minutes
    of inactivity.

    [...]

    The maintainer of the Genie system told me that he has no such
    logic implemented in his tool

    The maintainer is mistaken.

    If you look in a68g-io.c you will see that the function io_read_conv() returns -1 if read() returns EINTR more than MAX_RESTART+1 (257) times.

    If you look in a68-bits.c you will see that setitimer() is called with
    an interval of INTERRUPT_INTERVAL (5) seconds at the start and is
    called again whenever the handler gets run.

    Your read therefore fails after 258*5 = 1290 seconds.

    Which matches exactly the observed value. - Wow!


    (The intention of all this seems to be a to implement a cpu time
    limit, but it also has this presumably undesired effect.)

    On a system where read() is automatically restarted after SIGALRM
    is handled, none of this will happen.

    Many thanks!

    I'll forward that information and see what can be done about it.

    Janis

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.misc,comp.lang.c on Sat Oct 4 00:28:56 2025
    From Newsgroup: comp.lang.misc

    On 2025-10-03, Scott Lurndal <scott@slp53.sl.home> wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    The maintainer of the Genie system told me that he has no such
    logic implemented in his tool, and he suspected the libc as the
    source of the interrupted system call.

    Janis, Do you have some shell hack running with a background process that delivers an alarm signal, and is that going to the entire process group?

    run the application under strace to see the system call that was
    interrupted.

    $ strace -f -o syscall.tr genie -x 'read (newline)'

    Bingo; the system call and any signal handling details.

    Maybe the Genie run-time (is that accurate?) has some periodic signal to
    do something. Maybe that signal is being handled many times while
    it is sitting in that TTY read, and the signal handling is being careful
    to specify that a system call interrupted by the signal should be
    restarted. And maybe there is some race condition in that where it
    hiccups, resulting in an EINTR exposure.

    I dojn't see such a thing in the latest Genie tarball, but in the
    genie function in genie.c, this is called:

    void install_signal_handlers (void)
    {
    ABEND (signal (SIGINT, sigint_handler) == SIG_ERR, ERROR_ACTION, NO_TEXT);
    ABEND (signal (SIGSEGV, sigsegv_handler) == SIG_ERR, ERROR_ACTION, NO_TEXT);
    #if defined (SIGWINCH)
    ABEND (signal (SIGWINCH, sigwinch_handler) == SIG_ERR, ERROR_ACTION, NO_TEXT);
    #endif
    #if defined (BUILD_UNIX)
    ABEND (signal (SIGALRM, sigalrm_handler) == SIG_ERR, ERROR_ACTION, NO_TEXT);
    ABEND (signal (SIGPIPE, sigpipe_handler) == SIG_ERR, ERROR_ACTION, NO_TEXT);
    ABEND (signal (SIGTTIN, sigttin_handler) == SIG_ERR, ERROR_ACTION, NO_TEXT);
    #endif
    }

    It's using the ISO C signal function, which from the Posix point of
    view is obsolescent; sigaction should be used.

    On Linux, I think signal() has the BSD semantics for restarting;
    for every signal, SA_RESTART is used unless you use siginterrupt()
    to indicate otherwise for specific signals.

    I've also noticed that the I/O routines in a68g-io.c count EINTR
    events using a global variable (that is never reset to zero). Once
    it hits 256, they start reporting interruptions.

    If you had some interrupt happening every 5 seconds, it would take
    about 20 minutes to hit 256.

    Another finding: genie() calls this:

    (void) a68g_alarm (INTERRUPT_INTERVAL);

    INTERRUPT_INTERVAL is 5 seconds. It calls setitimer to start a periodic alarm.

    Even if that function were not called, if genie were to receive
    a SIGALRM from another process, its handler will call the above function
    to set up the interrupt.

    So we have proof that genie does sets up a periodic alarm as I suspected
    in my first paragraph. The interval does line up with roughly 20
    minutes, if we count 256 events as the I/O routines do.
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.misc,comp.lang.c on Sat Oct 4 02:41:05 2025
    From Newsgroup: comp.lang.misc

    On 04.10.2025 02:28, Kaz Kylheku wrote:
    On 2025-10-03, Scott Lurndal <scott@slp53.sl.home> wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    The maintainer of the Genie system told me that he has no such
    logic implemented in his tool, and he suspected the libc as the
    source of the interrupted system call.

    Janis, Do you have some shell hack running with a background process that delivers an alarm signal, and is that going to the entire process group?

    Nope.


    run the application under strace to see the system call that was
    interrupted.

    $ strace -f -o syscall.tr genie -x 'read (newline)'

    Bingo; the system call and any signal handling details.

    Maybe the Genie run-time (is that accurate?) has some periodic signal to
    do something. Maybe that signal is being handled many times while
    it is sitting in that TTY read, and the signal handling is being careful
    to specify that a system call interrupted by the signal should be
    restarted. And maybe there is some race condition in that where it
    hiccups, resulting in an EINTR exposure.

    I dojn't see such a thing in the latest Genie tarball, but in the
    genie function in genie.c, this is called:

    void install_signal_handlers (void)
    {
    ABEND (signal (SIGINT, sigint_handler) == SIG_ERR, ERROR_ACTION, NO_TEXT);
    ABEND (signal (SIGSEGV, sigsegv_handler) == SIG_ERR, ERROR_ACTION, NO_TEXT);
    #if defined (SIGWINCH)
    ABEND (signal (SIGWINCH, sigwinch_handler) == SIG_ERR, ERROR_ACTION, NO_TEXT);
    #endif
    #if defined (BUILD_UNIX)
    ABEND (signal (SIGALRM, sigalrm_handler) == SIG_ERR, ERROR_ACTION, NO_TEXT);
    ABEND (signal (SIGPIPE, sigpipe_handler) == SIG_ERR, ERROR_ACTION, NO_TEXT);
    ABEND (signal (SIGTTIN, sigttin_handler) == SIG_ERR, ERROR_ACTION, NO_TEXT);
    #endif
    }

    It's using the ISO C signal function, which from the Posix point of
    view is obsolescent; sigaction should be used.

    On Linux, I think signal() has the BSD semantics for restarting;
    for every signal, SA_RESTART is used unless you use siginterrupt()
    to indicate otherwise for specific signals.

    I've also noticed that the I/O routines in a68g-io.c count EINTR
    events using a global variable (that is never reset to zero). Once
    it hits 256, they start reporting interruptions.

    If you had some interrupt happening every 5 seconds, it would take
    about 20 minutes to hit 256.

    Another finding: genie() calls this:

    (void) a68g_alarm (INTERRUPT_INTERVAL);

    INTERRUPT_INTERVAL is 5 seconds. It calls setitimer to start a periodic alarm.

    Even if that function were not called, if genie were to receive
    a SIGALRM from another process, its handler will call the above function
    to set up the interrupt.

    So we have proof that genie does sets up a periodic alarm as I suspected
    in my first paragraph. The interval does line up with roughly 20
    minutes, if we count 256 events as the I/O routines do.

    Yeah, obviously the maintainer wasn't aware of that. Richard Tobin gave
    a similar reply and I forwarded it for consideration of a change or fix
    in Genie.

    Many thanks!

    Janis

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From richard@richard@cogsci.ed.ac.uk (Richard Tobin) to comp.lang.misc,comp.lang.c on Sat Oct 4 01:04:51 2025
    From Newsgroup: comp.lang.misc

    In article <20251003165522.137@kylheku.com>,
    Kaz Kylheku <643-408-1753@kylheku.com> wrote:

    On Linux, I think signal() has the BSD semantics for restarting;
    for every signal, SA_RESTART is used unless you use siginterrupt()
    to indicate otherwise for specific signals.

    Linux signal() has the System V semantics, and replacing the call to
    signal with sigaction and SA_RESTART fixes the problem.

    What I don't understand is why on my Mac the handler never seems to get
    called at all.

    -- Richard
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.misc,comp.lang.c on Sat Oct 4 01:07:57 2025
    From Newsgroup: comp.lang.misc

    On 2025-10-04, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    Yeah, obviously the maintainer wasn't aware of that. Richard Tobin gave
    a similar reply and I forwarded it for consideration of a change or fix
    in Genie.

    I still don't understand how Genie is getting the EINTR if the signals
    are registered with signal(), that having BSD semantics on Linux (thanks
    to libc), which is like having SA_RESTART in sigaction by default.

    It's right here:

    https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/signal.c

    signal is implemented on top of sigaction and uses SA_RESTART except
    for signals for which the program has opted out.

    That _sigintr mask is all zeros initially, manipulated by siginterrupt (adjacent sigintr.c file).
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.misc,comp.lang.c on Sat Oct 4 01:23:29 2025
    From Newsgroup: comp.lang.misc

    On 2025-10-04, Richard Tobin <richard@cogsci.ed.ac.uk> wrote:
    In article <20251003165522.137@kylheku.com>,
    Kaz Kylheku <643-408-1753@kylheku.com> wrote:

    On Linux, I think signal() has the BSD semantics for restarting;
    for every signal, SA_RESTART is used unless you use siginterrupt()
    to indicate otherwise for specific signals.

    Linux signal() has the System V semantics, and replacing the call to
    signal with sigaction and SA_RESTART fixes the problem.

    Am I looking at the wrong things in glibc; there must be another signal
    in a Linux-dependent directory?

    I can't find a definition of signal there.

    There is a sysdeps/posix/sys_signal.c which
    defines a __sysv_signal, along with this:

    weak_alias (__sysv_signal, sysv_signal)

    In sysdeps/posix/signal.c, the __bsd_signal function is aliased like
    this:

    weak_alias (__bsd_signal, bsd_signal)
    weak_alias (__bsd_signal, signal)
    weak_alias (__bsd_signal, ssignal)

    What I don't understand is why on my Mac the handler never seems to get called at all.

    Is it compiled out? The BUILD_UNIX preprocessor symbol would have to be
    absent, though.
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.misc,comp.lang.c on Sat Oct 4 01:28:33 2025
    From Newsgroup: comp.lang.misc

    On 2025-10-04, Richard Tobin <richard@cogsci.ed.ac.uk> wrote:
    In article <20251003165522.137@kylheku.com>,
    Kaz Kylheku <643-408-1753@kylheku.com> wrote:

    On Linux, I think signal() has the BSD semantics for restarting;
    for every signal, SA_RESTART is used unless you use siginterrupt()
    to indicate otherwise for specific signals.

    Linux signal() has the System V semantics, and replacing the call to
    signal with sigaction and SA_RESTART fixes the problem.

    Empirical test tracing signal to bsd_signal. So, bit of a mystery:

    $ cat > signal.c
    #include <signal.h>

    int main()
    {
    signal(SIGTERM, SIG_DFL);
    return 0;
    }

    $ make signal
    cc signal.c -o signal

    $ ldd signal
    linux-vdso.so.1 (0x000015555551b000)
    libc.so.6 => /lib64/libc.so.6 (0x0000155555200000)
    /lib64/ld-linux-x86-64.so.2 (0x000015555551d000)

    $ nm -D signal | grep signal
    U signal@GLIBC_2.2.5

    $ nm -D /lib64/libc.so.6 | grep signal
    000000000003e940 W bsd_signal@@GLIBC_2.2.5
    0000000000095620 T cnd_signal@GLIBC_2.28
    0000000000095620 T cnd_signal@@GLIBC_2.34
    U _dl_signal_error@GLIBC_PRIVATE
    U _dl_signal_exception@GLIBC_PRIVATE
    000000000003e980 W gsignal@@GLIBC_2.2.5
    000000000005bc00 T psignal@@GLIBC_2.2.5
    000000000008b2e0 T pthread_cond_signal@@GLIBC_2.3.2
    0000000000089f40 T pthread_cond_signal@GLIBC_2.2.5
    000000000003e940 W signal@@GLIBC_2.2.5
    00000000001144a0 T signalfd@@GLIBC_2.7
    000000000003e940 W ssignal@@GLIBC_2.2.5
    000000000009f830 T strsignal@@GLIBC_2.2.5
    000000000003f530 T __sysv_signal@@GLIBC_2.2.5
    000000000003f530 W sysv_signal@@GLIBC_2.2.5

    $ nm -D /lib64/libc.so.6 | grep 000000000003e940
    000000000003e940 W bsd_signal@@GLIBC_2.2.5
    000000000003e940 W signal@@GLIBC_2.2.5
    000000000003e940 W ssignal@@GLIBC_2.2.5
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.misc,comp.lang.c on Sat Oct 4 02:12:31 2025
    From Newsgroup: comp.lang.misc

    Kaz Kylheku <643-408-1753@kylheku.com> writes:
    On 2025-10-04, Richard Tobin <richard@cogsci.ed.ac.uk> wrote:
    In article <20251003165522.137@kylheku.com>,
    Kaz Kylheku <643-408-1753@kylheku.com> wrote:

    On Linux, I think signal() has the BSD semantics for restarting;
    for every signal, SA_RESTART is used unless you use siginterrupt()
    to indicate otherwise for specific signals.

    Linux signal() has the System V semantics, and replacing the call to
    signal with sigaction and SA_RESTART fixes the problem.

    Empirical test tracing signal to bsd_signal. So, bit of a mystery:

    $ man 2 signal
    ...
    The situation on Linux is as follows:

    * The kernel's signal() system call provides System V semantics.

    * By default, in glibc 2 and later, the signal() wrapper function does not invoke the
    kernel system call. Instead, it calls sigaction(2) using flags that supply BSD
    semantics. This default behavior is provided as long as the _BSD_SOURCE feature
    test macro is defined. By default, _BSD_SOURCE is defined; it is also implicitly
    defined if one defines _GNU_SOURCE, and can of course be explicitly defined.

    On glibc 2 and later, if the _BSD_SOURCE feature test macro is not defined, then
    signal() provides System V semantics. (The default implicit definition of
    _BSD_SOURCE is not provided if one invokes gcc(1) in one of its standard modes
    (-std=xxx or -ansi) or defines various other feature test macros such as
    _POSIX_SOURCE, _XOPEN_SOURCE, or _SVID_SOURCE; see feature_test_macros(7).)

    * The signal() function in Linux libc4 and libc5 provide System V semantics. If one
    on a libc5 system includes <bsd/signal.h> instead of <signal.h>, then signal() pro-
    vides BSD semantics.

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.misc,comp.lang.c on Sat Oct 4 02:13:33 2025
    From Newsgroup: comp.lang.misc

    richard@cogsci.ed.ac.uk (Richard Tobin) writes:
    In article <10bpkh1$25arg$1@dont-email.me>,
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    In context of a Genie (Algol 68) program, after leaving the
    terminal some minutes while the program was waiting in a 'read',
    the program terminated by an interrupt. So I set up this simple
    call to reproduce it... - it gets interrupted after ~21 minutes
    of inactivity.

    [...]

    The maintainer of the Genie system told me that he has no such
    logic implemented in his tool

    The maintainer is mistaken.

    If you look in a68g-io.c you will see that the function io_read_conv() >returns -1 if read() returns EINTR more than MAX_RESTART+1 (257) times.

    If you look in a68-bits.c you will see that setitimer() is called with
    an interval of INTERRUPT_INTERVAL (5) seconds at the start and is
    called again whenever the handler gets run.

    Your read therefore fails after 258*5 = 1290 seconds.

    (The intention of all this seems to be a to implement a cpu time
    limit, but it also has this presumably undesired effect.)

    SIGXCPU would be a better choice in these modern times.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.misc,comp.lang.c on Sat Oct 4 02:35:19 2025
    From Newsgroup: comp.lang.misc

    On Sat, 4 Oct 2025 01:04:51 -0000 (UTC), Richard Tobin wrote:

    What I don't understand is why on my Mac the handler never seems to get called at all.

    But itrCOs UNIX-<!!!
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From richard@richard@cogsci.ed.ac.uk (Richard Tobin) to comp.lang.misc,comp.lang.c on Sat Oct 4 12:52:58 2025
    From Newsgroup: comp.lang.misc

    In article <10bprrj$2l08$2@artemis.inf.ed.ac.uk>,
    Richard Tobin <richard@cogsci.ed.ac.uk> wrote:

    What I don't understand is why on my Mac the handler never seems to get >called at all.

    The answer seems to be that SIGALRM is blocked. The process appears
    to be inheriting this, as it varies depending on which shell and
    terminal program I am using.

    -- Richard
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.misc,comp.lang.c on Sat Oct 4 18:50:33 2025
    From Newsgroup: comp.lang.misc

    On 2025-10-04, Richard Tobin <richard@cogsci.ed.ac.uk> wrote:
    In article <10bprrj$2l08$2@artemis.inf.ed.ac.uk>,
    Richard Tobin <richard@cogsci.ed.ac.uk> wrote:

    What I don't understand is why on my Mac the handler never seems to get >>called at all.

    The answer seems to be that SIGALRM is blocked. The process appears
    to be inheriting this, as it varies depending on which shell and
    terminal program I am using.

    Aha, right; the signal masks. That is inherited across exec. Genie
    installs a handler for SIGALRM, but otherwise relies on the signal mask
    being clean.

    I remember dealing with this when working on a wrapper for
    a version control tool many years ago. Because I had a certain signal
    blocked, the forked/execed tool was not responding to it.
    I think it was SIGCHLD in fact, and that caused problems when
    that process started its own subprocesses like ssh.
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From richard@richard@cogsci.ed.ac.uk (Richard Tobin) to comp.lang.misc on Sun Oct 5 11:39:16 2025
    From Newsgroup: comp.lang.misc

    In article <86347z4ims.fsf@williamsburg.bawden.org>,
    Alan Bawden <alan@csail.mit.edu> wrote:

    It's not necessarily a timeout. Maybe something else in the system sets
    up an interrupt handler for some other reason. EINTR happens. Be prepared.

    BSD fixed this over 40 years ago, but unfortunately System V messed
    everything up and Posix insisted on supporting both.

    Use sigaction() with SA_RESTART instead of signal() and you shouldn't
    get EINTR for read().

    -- Richard
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.misc,comp.lang.c on Sun Oct 5 11:43:32 2025
    From Newsgroup: comp.lang.misc

    On 10/3/2025 5:18 PM, Richard Tobin wrote:
    In article <10bpkh1$25arg$1@dont-email.me>,
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    In context of a Genie (Algol 68) program, after leaving the
    terminal some minutes while the program was waiting in a 'read',
    the program terminated by an interrupt. So I set up this simple
    call to reproduce it... - it gets interrupted after ~21 minutes
    of inactivity.

    [...]

    The maintainer of the Genie system told me that he has no such
    logic implemented in his tool

    The maintainer is mistaken.

    If you look in a68g-io.c you will see that the function io_read_conv() returns -1 if read() returns EINTR more than MAX_RESTART+1 (257) times.

    Ohhh. Reminds me of debugging a race condition many years ago that used sem_wait. I noticed that it was not looping back around when EINTR was encountered.



    If you look in a68-bits.c you will see that setitimer() is called with
    an interval of INTERRUPT_INTERVAL (5) seconds at the start and is
    called again whenever the handler gets run.

    Your read therefore fails after 258*5 = 1290 seconds.

    (The intention of all this seems to be a to implement a cpu time
    limit, but it also has this presumably undesired effect.)

    On a system where read() is automatically restarted after SIGALRM
    is handled, none of this will happen.



    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Alan Bawden@alan@csail.mit.edu to comp.lang.misc on Mon Oct 6 04:05:42 2025
    From Newsgroup: comp.lang.misc

    richard@cogsci.ed.ac.uk (Richard Tobin) writes:

    In article <86347z4ims.fsf@williamsburg.bawden.org>,
    Alan Bawden <alan@csail.mit.edu> wrote:

    >It's not necessarily a timeout. Maybe something else in the system
    >sets up an interrupt handler for some other reason. EINTR happens.
    >Be prepared.

    BSD fixed this over 40 years ago, but unfortunately System V messed
    everything up and Posix insisted on supporting both.

    Use sigaction() with SA_RESTART instead of signal() and you shouldn't
    get EINTR for read().

    Oh! I hadn't realized that SA_RESTART was actually part of Posix! I
    thought it was a BSD thing that you couldn't use if you wanted to be
    fully portable. Since I've been programming in C on various flavors of
    Unix for about 40 years, I guess that may have been the case when I
    first started out, and I never noticed that things had changed.

    I notice that the sigaction(2) manual page on a recent FreeBSD install
    still says:

    The sigaction() system call is expected to conform to IEEE Std
    1003.1-1990 ("POSIX.1"). The SA_ONSTACK and SA_RESTART flags are
    Berkeley extensions, ...

    Which sure makes it sound like SA_RESTART might not exist elsewhere.
    Perhaps it didn't in the version of Posix referred to here, and the
    manual page hasn't been updated in a long time...

    So thank you for showing me something I wasn't aware of!
    --
    Alan Bawden
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From richard@richard@cogsci.ed.ac.uk (Richard Tobin) to comp.lang.misc on Mon Oct 6 10:46:14 2025
    From Newsgroup: comp.lang.misc

    In article <86y0po3161.fsf@williamsburg.bawden.org>,
    Alan Bawden <alan@csail.mit.edu> wrote:

    I notice that the sigaction(2) manual page on a recent FreeBSD install
    still says:

    The sigaction() system call is expected to conform to IEEE Std
    1003.1-1990 ("POSIX.1"). The SA_ONSTACK and SA_RESTART flags are
    Berkeley extensions, ...

    Which sure makes it sound like SA_RESTART might not exist elsewhere.
    Perhaps it didn't in the version of Posix referred to here, and the
    manual page hasn't been updated in a long time...

    They should update that! I'd forgotten - if I ever knew - that this
    wasn't in the first version of Posix. It's in version 2 of the Single
    Unix Specification (1997); it may not have been formally in Posix
    until the two became the same thing in 2001.

    -- Richard
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.misc on Mon Oct 6 22:04:00 2025
    From Newsgroup: comp.lang.misc

    On Mon, 06 Oct 2025 04:05:42 -0400, Alan Bawden wrote:

    I notice that the sigaction(2) manual page on a recent FreeBSD install
    still says:

    The sigaction() system call is expected to conform to IEEE Std
    1003.1-1990 ("POSIX.1"). The SA_ONSTACK and SA_RESTART flags are
    Berkeley extensions, ...

    Which sure makes it sound like SA_RESTART might not exist elsewhere.

    <https://manpages.debian.org/sigaction(2)> says in the HISTORY section:

    POSIX.1-1990 specified only SA_NOCLDSTOP. POSIX.1-2001 added
    SA_NOCLDWAIT, SA_NODEFER, SA_ONSTACK, SA_RESETHAND, SA_RESTART,
    and SA_SIGINFO as XSI extensions. POSIX.1-2008 moved SA_NODEFER,
    SA_RESETHAND, SA_RESTART, and SA_SIGINFO to the base
    specifications. Use of these latter values in sa_flags may be less
    portable in applications intended for older UNIX implementations.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.misc on Tue Oct 7 16:29:31 2025
    From Newsgroup: comp.lang.misc

    Notice: Marcel published a new Genie release 3.10 - also with an
    updated documentation - that has (besides other things) this issue
    fixed.

    Thanks to all who have contributed with the analysis of the issue
    and explanations!

    Janis


    On 04.10.2025 00:59, Janis Papanagnou wrote:
    I'm not sure where this effect originated from; whether from the
    "host language" (Algol 68/Genie), the underlying implementation
    language ("C", libc), or from the OS (Linux) or the distribution
    setup. - Maybe someone has an idea what's going on here...?

    In context of a Genie (Algol 68) program, after leaving the
    terminal some minutes while the program was waiting in a 'read',
    the program terminated by an interrupt. So I set up this simple
    call to reproduce it... - it gets interrupted after ~21 minutes
    of inactivity.


    $ date ; genie -x 'read (newline)' ; date
    Fr., 03. Oktober 2025, 16:09:29 (CEST)
    1 (read (newline))
    1
    a68g: runtime error: 1: error transputting PROC (REF FILE) VOID value, interrupted system call, in VOID
    closed-clause starting at "(" in this line.
    Fr., 03. Oktober 2025, 16:30:59 (CEST)


    The maintainer of the Genie system told me that he has no such
    logic implemented in his tool, and he suspected the libc as the
    source of the interrupted system call.

    Has anyone observed such behavior (maybe in similar contexts,
    when waiting for input, where no own interrupt timer has been
    set up)?

    Thanks.

    Janis


    --- Synchronet 3.21a-Linux NewsLink 1.2