mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 07:43:07 +02:00
commit bash-20210209 snapshot
This commit is contained in:
@@ -9555,3 +9555,24 @@ lib/malloc/malloc.c
|
||||
old size and new size are both bigger than the mmap threshold
|
||||
- internal_realloc: call internal_remap if the old size and new size
|
||||
are both above the threshold where we use mmap for allocation
|
||||
|
||||
2/10
|
||||
----
|
||||
include/timer.h
|
||||
- new file, declaration for a timer struct to be used by a set of
|
||||
functions to implement timers using SIGALRM or select/pselect
|
||||
|
||||
lib/sh/timers.c
|
||||
- new file, set of functions to manipulate timer objects and timeouts
|
||||
using SIGALRM or select/pselect. Inspired by a patch from
|
||||
Koichi Murase <myoga.murase@gmail.com>. Not used yet
|
||||
|
||||
2/11
|
||||
----
|
||||
builtins/read.def
|
||||
- read_builtin: if there is a timeout set, block SIGCHLD around calls
|
||||
to zread and its siblings, or calls to readline for `read -e', so
|
||||
SIGCHLD (and the consequent waitpid) doesn't interrupt the read.
|
||||
Fixes bug reported by Koichi Murase <myoga.murase@gmail.com>, but
|
||||
there may be a different fix coming
|
||||
|
||||
|
||||
@@ -230,6 +230,7 @@ include/shtty.h f
|
||||
include/stat-time.h f
|
||||
include/stdc.h f
|
||||
include/systimes.h f
|
||||
include/timer.h f
|
||||
include/typemax.h f
|
||||
include/unionwait.h f
|
||||
lib/glob/Makefile.in f
|
||||
@@ -449,6 +450,7 @@ lib/sh/strtoul.c f
|
||||
lib/sh/strtoull.c f
|
||||
lib/sh/strtoumax.c f
|
||||
lib/sh/strtrans.c f
|
||||
lib/sh/timers.c f
|
||||
lib/sh/times.c f
|
||||
lib/sh/timeval.c f
|
||||
lib/sh/tmpfile.c f
|
||||
|
||||
+2
-1
@@ -232,7 +232,8 @@ SHLIB_SOURCE = ${SH_LIBSRC}/clktck.c ${SH_LIBSRC}/getcwd.c \
|
||||
${SH_LIBSRC}/fnxform.c ${SH_LIBSRC}/unicode.c \
|
||||
${SH_LIBSRC}/wcswidth.c ${SH_LIBSRC}/wcsnwidth.c \
|
||||
${SH_LIBSRC}/shmbchar.c ${SH_LIBSRC}/utf8.c \
|
||||
${SH_LIBSRC}/random.c ${SH_LIBSRC}/gettimeofday.c
|
||||
${SH_LIBSRC}/random.c ${SH_LIBSRC}/gettimeofday.c \
|
||||
${SH_LIBSRC}/timers.c
|
||||
|
||||
SHLIB_LIB = -lsh
|
||||
SHLIB_LIBNAME = libsh.a
|
||||
|
||||
+1
-1
@@ -4639,7 +4639,7 @@ bash_event_hook ()
|
||||
bashline_reset_event_hook ();
|
||||
|
||||
/* posix mode SIGINT during read -e. We only get here if SIGINT is trapped. */
|
||||
if (posixly_correct && this_shell_builtin == read_builtin && sig == 2)
|
||||
if (posixly_correct && this_shell_builtin == read_builtin && sig == SIGINT)
|
||||
{
|
||||
last_command_exit_value = 128|SIGINT;
|
||||
throw_to_top_level ();
|
||||
|
||||
@@ -192,6 +192,7 @@ read_builtin (list)
|
||||
struct stat tsb;
|
||||
SHELL_VAR *var;
|
||||
TTYSTRUCT ttattrs, ttset;
|
||||
sigset_t chldset, prevset;
|
||||
#if defined (ARRAY_VARS)
|
||||
WORD_LIST *alist;
|
||||
int vflags;
|
||||
@@ -388,6 +389,12 @@ read_builtin (list)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (SIGCHLD)
|
||||
sigemptyset (&chldset);
|
||||
sigprocmask (SIG_BLOCK, (sigset_t *)0, &chldset);
|
||||
sigaddset (&chldset, SIGCHLD);
|
||||
#endif
|
||||
|
||||
begin_unwind_frame ("read_builtin");
|
||||
|
||||
#if defined (BUFFERED_INPUT)
|
||||
@@ -576,6 +583,10 @@ read_builtin (list)
|
||||
free (rlbuf);
|
||||
rlbuf = (char *)0;
|
||||
}
|
||||
#if defined (SIGCHLD)
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
sigprocmask (SIG_SETMASK, &chldset, &prevset);
|
||||
#endif
|
||||
if (rlbuf == 0)
|
||||
{
|
||||
reading = 1;
|
||||
@@ -583,6 +594,10 @@ read_builtin (list)
|
||||
reading = 0;
|
||||
rlind = 0;
|
||||
}
|
||||
#if defined (SIGCHLD)
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
sigprocmask (SIG_SETMASK, &prevset, (sigset_t *)0);
|
||||
#endif
|
||||
if (rlbuf == 0)
|
||||
{
|
||||
eof = 1;
|
||||
@@ -606,12 +621,22 @@ read_builtin (list)
|
||||
reading = 1;
|
||||
CHECK_ALRM;
|
||||
errno = 0;
|
||||
|
||||
#if defined (SIGCHLD)
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
sigprocmask (SIG_SETMASK, &chldset, &prevset);
|
||||
#endif
|
||||
if (unbuffered_read == 2)
|
||||
retval = posixly_correct ? zreadintr (fd, &c, 1) : zreadn (fd, &c, nchars - nr);
|
||||
else if (unbuffered_read)
|
||||
retval = posixly_correct ? zreadintr (fd, &c, 1) : zread (fd, &c, 1);
|
||||
else
|
||||
retval = posixly_correct ? zreadcintr (fd, &c) : zreadc (fd, &c);
|
||||
#if defined (SIGCHLD)
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
sigprocmask (SIG_SETMASK, &prevset, (sigset_t *)0);
|
||||
#endif
|
||||
|
||||
reading = 0;
|
||||
|
||||
if (retval <= 0)
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/* timer.h -- data structures used by the shell timers in lib/sh/timers.c */
|
||||
|
||||
/* Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "bashjmp.h"
|
||||
typedef struct _shtimer
|
||||
{
|
||||
struct timeval tmout;
|
||||
|
||||
int fd;
|
||||
int flags;
|
||||
|
||||
int alrmflag; /* should be set by alrm_handler */
|
||||
|
||||
SigHandler *alrm_handler;
|
||||
SigHandler *old_handler;
|
||||
|
||||
procenv_t jmpenv;
|
||||
|
||||
void (*handler) (struct _shtimer *); /* XXX - unused right now */
|
||||
PTR_T *data; /* reserved */
|
||||
} sh_timer;
|
||||
|
||||
#define SHTIMER_ALARM 0x01 /* mutually exclusive */
|
||||
#define SHTIMER_SELECT 0x02
|
||||
#define SHTIMER_LONGJMP 0x04
|
||||
|
||||
#define SHTIMER_SIGSET 0x100
|
||||
|
||||
extern sh_timer *shtimer_alloc (void);
|
||||
extern void shtimer_flush (sh_timer *);
|
||||
extern void shtimer_dispose (sh_timer *);
|
||||
|
||||
extern void shtimer_set (sh_timer *, time_t, long);
|
||||
extern void shtimer_unset (sh_timer *);
|
||||
|
||||
extern void shtimer_cleanup (sh_timer *);
|
||||
extern void shtimer_clear (sh_timer *);
|
||||
|
||||
extern int shtimer_chktimeout (sh_timer *);
|
||||
|
||||
extern int shtimer_select (sh_timer *);
|
||||
extern int shtimer_alrm (sh_timer *);
|
||||
+12
-2
@@ -93,7 +93,7 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
|
||||
wcsdup.c fpurge.c zgetline.c mbscmp.c uconvert.c ufuncs.c \
|
||||
casemod.c dprintf.c input_avail.c mbscasecmp.c fnxform.c \
|
||||
strchrnul.c unicode.c wcswidth.c wcsnwidth.c shmbchar.c strdup.c \
|
||||
utf8.c random.c gettimeofday.c
|
||||
utf8.c random.c gettimeofday.c timers.c
|
||||
|
||||
# The header files for this library.
|
||||
HSOURCES =
|
||||
@@ -108,7 +108,7 @@ OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \
|
||||
fmtullong.o fmtumax.o zcatfd.o zmapfd.o winsize.o wcsdup.o \
|
||||
fpurge.o zgetline.o mbscmp.o uconvert.o ufuncs.o casemod.o \
|
||||
input_avail.o mbscasecmp.o fnxform.o unicode.o shmbchar.o \
|
||||
utf8.o random.o gettimeofday.o wcsnwidth.o ${LIBOBJS}
|
||||
utf8.o random.o gettimeofday.o timers.o wcsnwidth.o ${LIBOBJS}
|
||||
|
||||
SUPPORT = Makefile
|
||||
|
||||
@@ -197,6 +197,7 @@ strtoul.o: strtoul.c
|
||||
strtoull.o: strtoull.c
|
||||
strtoumax.o: strtoumax.c
|
||||
strtrans.o: strtrans.c
|
||||
timers.o: timers.c
|
||||
times.o: times.c
|
||||
timeval.o: timeval.c
|
||||
tmpfile.o: tmpfile.c
|
||||
@@ -277,6 +278,7 @@ strtoul.o: ${BUILD_DIR}/config.h
|
||||
strtoull.o: ${BUILD_DIR}/config.h
|
||||
strtoumax.o: ${BUILD_DIR}/config.h
|
||||
strtrans.o: ${BUILD_DIR}/config.h
|
||||
timers.o: ${BUILD_DIR}/config.h
|
||||
times.o: ${BUILD_DIR}/config.h
|
||||
timeval.o: ${BUILD_DIR}/config.h
|
||||
tmpfile.o: ${BUILD_DIR}/config.h ${topdir}/config-top.h
|
||||
@@ -620,6 +622,14 @@ fnxform.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
|
||||
shmbchar.o: ${BASHINCDIR}/shmbchar.h
|
||||
shmbchar.o: ${BASHINCDIR}/shmbutil.h
|
||||
|
||||
timers.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
timers.o: ${BASHINCDIR}/stdc.h
|
||||
timers.o: ${topdir}/xmalloc.h ${topdir}/sig.h
|
||||
timers.o: ${BASHINCDIR}/posixtime.h ${BASHINCDIR}/stat-time.h
|
||||
timers.o: ${BASHINCDIR}/posixselect.h
|
||||
timers.o: ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
|
||||
timers.o: ${BASHINCDIR}/timer.h
|
||||
|
||||
unicode.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
unicode.o: ${BASHINCDIR}/stdc.h
|
||||
unicode.o: ${topdir}/xmalloc.h
|
||||
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
/* timers - functions to manage shell timers */
|
||||
|
||||
/* Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "bashtypes.h"
|
||||
#include "posixtime.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_SELECT)
|
||||
# include "posixselect.h"
|
||||
# include "stat-time.h"
|
||||
#endif
|
||||
|
||||
#include "sig.h"
|
||||
#include "bashjmp.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
#include "timer.h"
|
||||
|
||||
#include <errno.h>
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
extern unsigned int falarm (unsigned int, unsigned int);
|
||||
|
||||
sh_timer *
|
||||
shtimer_alloc (void)
|
||||
{
|
||||
sh_timer *r;
|
||||
|
||||
r = (sh_timer *)xmalloc (sizeof (sh_timer));
|
||||
shtimer_flush (r);
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
shtimer_flush (sh_timer *t)
|
||||
{
|
||||
t->tmout.tv_sec = 0;
|
||||
t->tmout.tv_usec = 0;
|
||||
|
||||
t->fd = t->flags = t->alrmflag = 0;
|
||||
|
||||
t->alrm_handler = t->old_handler = 0;
|
||||
|
||||
memset (t->jmpenv, '\0', sizeof (t->jmpenv));
|
||||
|
||||
t->handler = 0;
|
||||
t->data = 0;
|
||||
}
|
||||
|
||||
void
|
||||
shtimer_dispose (sh_timer *t)
|
||||
{
|
||||
free (t);
|
||||
}
|
||||
|
||||
/* We keep the timer as an offset into the future from the time it's set. */
|
||||
void
|
||||
shtimer_set (sh_timer *t, time_t sec, long usec)
|
||||
{
|
||||
struct timeval now;
|
||||
|
||||
if (t->flags & SHTIMER_ALARM)
|
||||
{
|
||||
t->alrmflag = 0; /* just paranoia */
|
||||
t->old_handler = set_signal_handler (SIGALRM, t->alrm_handler);
|
||||
t->flags |= SHTIMER_SIGSET;
|
||||
falarm (t->tmout.tv_sec = sec, t->tmout.tv_usec = usec);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gettimeofday (&now, 0) < 0)
|
||||
{
|
||||
now.tv_sec = 0;
|
||||
now.tv_usec = 0;
|
||||
}
|
||||
t->tmout.tv_sec = now.tv_sec + sec;
|
||||
t->tmout.tv_usec = now.tv_usec + usec;
|
||||
if (t->tmout.tv_usec > USEC_PER_SEC)
|
||||
{
|
||||
t->tmout.tv_sec++;
|
||||
t->tmout.tv_usec -= USEC_PER_SEC;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
shtimer_unset (sh_timer *t)
|
||||
{
|
||||
t->tmout.tv_sec = 0;
|
||||
t->tmout.tv_usec = 0;
|
||||
|
||||
if (t->flags & SHTIMER_ALARM)
|
||||
{
|
||||
t->alrmflag = 0;
|
||||
falarm (0, 0);
|
||||
if (t->old_handler && (t->flags & SHTIMER_SIGSET))
|
||||
{
|
||||
set_signal_handler (SIGALRM, t->old_handler);
|
||||
t->flags &= ~SHTIMER_SIGSET;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
shtimer_cleanup (sh_timer *t)
|
||||
{
|
||||
shtimer_unset (t);
|
||||
}
|
||||
|
||||
void
|
||||
shtimer_clear (sh_timer *t)
|
||||
{
|
||||
shtimer_unset (t);
|
||||
shtimer_dispose (t);
|
||||
}
|
||||
|
||||
int
|
||||
shtimer_chktimeout (sh_timer *t)
|
||||
{
|
||||
struct timeval now;
|
||||
int r;
|
||||
|
||||
/* Use the flag to avoid returning sigalrm_seen here */
|
||||
if (t->flags & SHTIMER_ALARM)
|
||||
return t->alrmflag;
|
||||
|
||||
/* Could check a flag for this */
|
||||
if (t->tmout.tv_sec == 0 && t->tmout.tv_usec == 0)
|
||||
return 0;
|
||||
|
||||
if (gettimeofday (&now, 0) < 0)
|
||||
return 0;
|
||||
r = ((now.tv_sec > t->tmout.tv_sec) ||
|
||||
(now.tv_sec == t->tmout.tv_sec && now.tv_usec >= t->tmout.tv_usec));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#if defined (HAVE_SELECT) || defined (HAVE_PSELECT)
|
||||
int
|
||||
shtimer_select (sh_timer *t)
|
||||
{
|
||||
int r;
|
||||
sigset_t blocked_sigs, prevmask;
|
||||
struct timeval now, tv;
|
||||
fd_set readfds;
|
||||
#if defined (HAVE_PSELECT)
|
||||
struct timespec ts;
|
||||
#endif
|
||||
|
||||
/* We don't want a SIGCHLD to interrupt this */
|
||||
sigemptyset (&blocked_sigs);
|
||||
# if defined (SIGCHLD)
|
||||
sigaddset (&blocked_sigs, SIGCHLD);
|
||||
# endif
|
||||
|
||||
if (gettimeofday (&now, 0) < 0)
|
||||
{
|
||||
if (t->flags & SHTIMER_LONGJMP)
|
||||
sh_longjmp (t->jmpenv, 1);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If the timer has already expired, return immediately */
|
||||
if ((now.tv_sec > t->tmout.tv_sec) ||
|
||||
(now.tv_sec == t->tmout.tv_sec && now.tv_usec >= t->tmout.tv_usec))
|
||||
{
|
||||
if (t->flags & SHTIMER_LONGJMP)
|
||||
sh_longjmp (t->jmpenv, 1);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* compute timeout */
|
||||
tv.tv_sec = t->tmout.tv_sec - now.tv_sec;
|
||||
tv.tv_usec = t->tmout.tv_usec - now.tv_usec;
|
||||
if (tv.tv_usec < 0)
|
||||
{
|
||||
tv.tv_sec--;
|
||||
tv.tv_usec += USEC_PER_SEC;
|
||||
}
|
||||
|
||||
#if defined (HAVE_PSELECT)
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec * 1000;
|
||||
#else
|
||||
sigemptyset (&prevmask);
|
||||
#endif /* !HAVE_PSELECT */
|
||||
|
||||
FD_ZERO (&readfds);
|
||||
FD_SET (t->fd, &readfds);
|
||||
|
||||
#if defined (HAVE_PSELECT)
|
||||
r = pselect(t->fd + 1, &readfds, (fd_set *)0, (fd_set *)0, &ts, &blocked_sigs);
|
||||
#else
|
||||
sigprocmask (SIG_SETMASK, &blocked_sigs, &prevmask);
|
||||
r = select(t->fd + 1, &readfds, (fd_set *)0, (fd_set *)0, &tv);
|
||||
sigprocmask (SIG_SETMASK, &prevmask, NULL);
|
||||
#endif
|
||||
|
||||
if (r < 0)
|
||||
return r; /* caller will handle */
|
||||
else if (r == 0 && (t->flags & SHTIMER_LONGJMP))
|
||||
sh_longjmp (t->jmpenv, 1);
|
||||
else
|
||||
return r;
|
||||
}
|
||||
#endif /* !HAVE_TIMEVAL || !HAVE_SELECT */
|
||||
|
||||
int
|
||||
shtimer_alrm (sh_timer *t)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -165,7 +165,8 @@ extern struct user_info current_user;
|
||||
/* Structure in which to save partial parsing state when doing things like
|
||||
PROMPT_COMMAND and bash_execute_unix_command execution. */
|
||||
|
||||
typedef struct _sh_parser_state_t {
|
||||
typedef struct _sh_parser_state_t
|
||||
{
|
||||
|
||||
/* parsing state */
|
||||
int parser_state;
|
||||
@@ -208,7 +209,8 @@ typedef struct _sh_parser_state_t {
|
||||
REDIRECT *redir_stack[HEREDOC_MAX];
|
||||
} sh_parser_state_t;
|
||||
|
||||
typedef struct _sh_input_line_state_t {
|
||||
typedef struct _sh_input_line_state_t
|
||||
{
|
||||
char *input_line;
|
||||
size_t input_line_index;
|
||||
size_t input_line_size;
|
||||
|
||||
Reference in New Issue
Block a user