Skip to content

Commit

Permalink
Use interruptible iopen() to open input file.
Browse files Browse the repository at this point in the history
Opening the read side of a fifo blocks until someone opens the write
side. SIGINT doesn't interrupt that block because less catches SIGINT.
Use new function iopen() to open the file; iopen can be interrupted
by intio() which is called from the signal handler.

This makes SIGINT work correctly, but SIGTSTP doesn't yet work as
expected: it doesn't stop the process, it just aborts the iopen like SIGINT.
  • Loading branch information
gwsw committed Nov 16, 2024
1 parent de3e84f commit ca59eda
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 30 deletions.
15 changes: 14 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,9 @@ AH_TEMPLATE([HAVE_FILENO],
AH_TEMPLATE([HAVE_ERRNO],
[Define HAVE_ERRNO if you have the errno variable.])
AH_TEMPLATE([MUST_DEFINE_ERRNO],
[Define MUST_DEFINE_ERRNO if you have errno but it is not define in errno.h.])
[Define MUST_DEFINE_ERRNO if you have errno but it is not defined in errno.h.])
AH_TEMPLATE([HAVE_SETTABLE_ERRNO],
[Define HAVE_SETTABLE_ERRNO if the errno variable can be assigned to.])
AH_TEMPLATE([HAVE_SYS_ERRLIST],
[Define HAVE_SYS_ERRLIST if you have the sys_errlist[] variable.])
AH_TEMPLATE([HAVE_OSPEED],
Expand Down Expand Up @@ -320,6 +322,17 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#endif]], [[extern int errno; static int x; x = errno;]])],[AC_MSG_RESULT(yes - must define); AC_DEFINE(HAVE_ERRNO) AC_DEFINE(MUST_DEFINE_ERRNO)],[AC_MSG_RESULT(no)])
fi

have_settable_errno=no
if test $have_errno = yes; then
AC_MSG_CHECKING(for settable errno)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#if HAVE_ERRNO_H
#include <errno.h>
#else
extern int errno;
#endif]], [[errno = 0;]])],[AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SETTABLE_ERRNO)],[])
fi

AC_MSG_CHECKING(for locale)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <locale.h>
#include <ctype.h>
Expand Down
1 change: 1 addition & 0 deletions defines.ds
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@
#define HAVE_ERRNO 1
#define MUST_DEFINE_ERRNO 1
#endif
#define HAVE_SETTABLE_ERRNO 1

/* Define HAVE_SYS_ERRLIST if you have the sys_errlist[] variable */
#define HAVE_SYS_ERRLIST 1
Expand Down
5 changes: 3 additions & 2 deletions defines.o2
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,11 @@
#define HAVE_FILENO 1

/* Define HAVE_ERRNO if you have the errno variable */
/* Define MUST_DEFINE_ERRNO if you have errno but it is not define
* in errno.h */
#define HAVE_ERRNO 1
/* Define MUST_DEFINE_ERRNO if you have errno but it is not defined in errno.h */
/* #undef MUST_DEFINE_ERRNO */
/* Define HAVE_SETTABLE_ERRNO if the errno variable can be assigned to. */
#define HAVE_SETTABLE_ERRNO 1

/* Define HAVE_SYS_ERRLIST if you have the sys_errlist[] variable */
#define HAVE_SYS_ERRLIST 1
Expand Down
5 changes: 3 additions & 2 deletions defines.o9
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,11 @@
#define HAVE_FILENO 1

/* Define HAVE_ERRNO if you have the errno variable */
/* Define MUST_DEFINE_ERRNO if you have errno but it is not define
* in errno.h */
#define HAVE_ERRNO 1
/* Define MUST_DEFINE_ERRNO if you have errno but it is not defined in errno.h */
#define MUST_DEFINE_ERRNO 0
/* Define HAVE_SETTABLE_ERRNO if the errno variable can be assigned to. */
#define HAVE_SETTABLE_ERRNO 1

/* Define HAVE_SYS_ERRLIST if you have the sys_errlist[] variable */
#define HAVE_SYS_ERRLIST 0
Expand Down
5 changes: 3 additions & 2 deletions defines.wn
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,11 @@
#define HAVE_FILENO 1

/* Define HAVE_ERRNO if you have the errno variable */
/* Define MUST_DEFINE_ERRNO if you have errno but it is not define
* in errno.h */
#define HAVE_ERRNO 1
/* Define MUST_DEFINE_ERRNO if you have errno but it is not defined in errno.h */
#define MUST_DEFINE_ERRNO 0
/* Define HAVE_SETTABLE_ERRNO if the errno variable can be assigned to. */
#define HAVE_SETTABLE_ERRNO 1

/* Define HAVE_SYS_ERRLIST if you have the sys_errlist[] variable */
#define HAVE_SYS_ERRLIST 1
Expand Down
2 changes: 1 addition & 1 deletion edit.c
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ public int edit_ifile(IFILE ifile)
error("%s", &parg);
free(p);
return edit_error(filename, alt_filename, altpipe, ifile);
} else if ((f = open(open_filename, OPEN_READ)) < 0)
} else if ((f = iopen(open_filename, OPEN_READ)) < 0)
{
/*
* Got an error trying to open it.
Expand Down
53 changes: 41 additions & 12 deletions os.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#if MUST_DEFINE_ERRNO
extern int errno;
#endif
#if HAVE_VALUES_H
#include <values.h>
#endif
Expand Down Expand Up @@ -66,13 +69,15 @@ static lbool any_data = FALSE;
#define LONG_JUMP longjmp
#endif

public int reading;
static lbool reading;
static lbool opening;
public lbool waiting_for_data;
public int consecutive_nulls = 0;

/* Milliseconds to wait for data before displaying "waiting for data" message. */
static int waiting_for_data_delay = 4000;
static jmp_buf read_label;
static jmp_buf open_label;

extern int sigs;
extern int ignore_eoi;
Expand Down Expand Up @@ -163,7 +168,7 @@ public int supports_ctrl_x(void)

/*
* Like read() system call, but is deliberately interruptible.
* A call to intread() from a signal handler will interrupt
* A call to intio() from a signal handler will interrupt
* any pending iread().
*/
public ssize_t iread(int fd, unsigned char *buf, size_t len)
Expand All @@ -190,7 +195,7 @@ public ssize_t iread(int fd, unsigned char *buf, size_t len)
if (!reading && SET_JUMP(read_label))
{
/*
* We jumped here from intread.
* We jumped here from intio.
*/
reading = FALSE;
#if HAVE_SIGPROCMASK
Expand Down Expand Up @@ -292,9 +297,6 @@ public ssize_t iread(int fd, unsigned char *buf, size_t len)
/*
* Certain values of errno indicate we should just retry the read.
*/
#if MUST_DEFINE_ERRNO
extern int errno;
#endif
#ifdef EINTR
if (errno == EINTR)
goto start;
Expand All @@ -314,11 +316,41 @@ public ssize_t iread(int fd, unsigned char *buf, size_t len)
}

/*
* Interrupt a pending iread().
* Like open() system call, but is interruptible.
*/
public void intread(void)
public int iopen(constant char *filename, int flags)
{
LONG_JUMP(read_label, 1);
int r;
if (!opening && SET_JUMP(open_label))
{
opening = FALSE;
sigs = 0;
#if HAVE_SETTABLE_ERRNO
#ifdef EINTR
errno = EINTR;
#endif
#endif
return -1;
}
opening = TRUE;
r = open(filename, flags);
opening = FALSE;
return r;
}

/*
* Interrupt a pending iopen() or iread().
*/
public void intio(void)
{
if (opening)
{
LONG_JUMP(open_label, 1);
}
if (reading)
{
LONG_JUMP(read_label, 1);
}
}

/*
Expand Down Expand Up @@ -363,9 +395,6 @@ public char * errno_message(constant char *filename)
char *m;
size_t len;
#if HAVE_ERRNO
#if MUST_DEFINE_ERRNO
extern int errno;
#endif
p = strerror(errno);
#else
p = "cannot open";
Expand Down
16 changes: 6 additions & 10 deletions signal.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <errno.h>
/*
* Copyright (C) 1984-2024 Mark Nudelman
*
Expand All @@ -15,7 +16,7 @@
* At some convenient time, the mainline code checks to see if any
* signals need processing by calling psignal().
* If we happen to be reading from a file [in iread()] at the time
* the signal is received, we call intread to interrupt the iread.
* the signal is received, we call intio to interrupt the iread.
*/

#include "less.h"
Expand All @@ -29,7 +30,6 @@ public int sigs;
extern int sc_width, sc_height;
extern int linenums;
extern int wscroll;
extern int reading;
extern int quit_on_intr;
extern long jump_sline_fraction;

Expand Down Expand Up @@ -59,8 +59,7 @@ static RETSIGTYPE u_interrupt(int type)
#if HILITE_SEARCH
set_filter_pattern(NULL, 0);
#endif
if (reading)
intread(); /* May longjmp */
intio();
}
#endif

Expand All @@ -74,8 +73,7 @@ static RETSIGTYPE stop(int type)
(void) type;
LSIGNAL(SIGTSTP, stop);
sigs |= S_STOP;
if (reading)
intread();
intio();
}
#endif

Expand Down Expand Up @@ -107,8 +105,7 @@ public RETSIGTYPE winch(int type)
return;
#endif
sigs |= S_WINCH;
if (reading)
intread();
intio();
}
#endif

Expand Down Expand Up @@ -153,8 +150,7 @@ static void sigusr(constant char *var)
if (isnullenv(cmd))
return;
ungetsc(cmd);
if (reading)
intread();
intio();
}

static RETSIGTYPE sigusr1(int type)
Expand Down

0 comments on commit ca59eda

Please sign in to comment.