Sysop: | Amessyroom |
---|---|
Location: | Fayetteville, NC |
Users: | 27 |
Nodes: | 6 (0 / 6) |
Uptime: | 41:12:15 |
Calls: | 631 |
Calls today: | 2 |
Files: | 1,187 |
D/L today: |
24 files (29,813K bytes) |
Messages: | 174,724 |
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.
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.
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)'
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.
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
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.
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.
run the application under strace to see the system call that was
interrupted.
$ strace -f -o syscall.tr genie -x 'read (newline)'
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.
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.
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.
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.
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.
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:
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.)
What I don't understand is why on my Mac the handler never seems to get called at all.
What I don't understand is why on my Mac the handler never seems to get >called at all.
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.
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.
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.
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...
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.
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