diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index d9750117..15bb4285 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -13227,7 +13227,7 @@ subst.c jobs.c - bgp_delindex: make sure to set ps->pid to NO_PID so we more effectively remove it from the hash table. It shouldn't matter as - long as nothing in pidstat_table points to it, but + long as nothing in pidstat_table points to it, but better to be safe - bgp_delete,bgp_search: generalize previous collision detection to loop detection: abort search if we are going to go back to the first index we tried @@ -14545,3 +14545,108 @@ execute_cmd.c and a status and mark the coproc as dead and having been reaped with that status. Used by child processes who want to invalidate the coproc's pid + + 12/5 + ---- +subst.c + - process_substitute: instead of just having a flag to denote that a + file descriptor is connected to a process substitution, store the + pid of the child process (still needs work) + - find_procsub_child,set_procsub_status,reap_procsubs: utility + functions to allow the job control code to detect that a process + substitution child has died and deallocate the file descriptors + or pathname + +subst.h + - find_procsub_child,set_procsub_status,reap_procsubs: extern + declarations + +nojobs.c + - set_pid_status: if we are reaping a process substitution, call + set_procsub_status to record the fact + +jobs.c + - waitchld: if we are reaping a process substitution, call + set_procsub_status to record the fact. Doesn't really do anything + yet + + 12/6 + ---- +execute_cmd.c + - execute_command: don't call unlink_fifo_list if we're in the + middle of executing a list of commands (executing_list != 0). + Partial fix for bug reported by Stephane Chazelas + + - execute_simple_command: don't close process substitution file + descriptors in the parent after forking children in a pipeline; + defer until pipeline completes, since parent may have inherited + fds from a calling scope (e.g., via `.'). EXPERIMENTAL + - execute_disk_command: don't close process substitution file + descriptors in the parent after forking the child. EXPERIMENTAL + + 12/7 + ---- +doc/bash.1,lib/readline/doc/{readline.3,rluser.texi} + - show-mode-in-prompt: clarify that this must be enabled before the + vi and emacs mode strings are prefixed to the prompt. Report from + Rob Foehl + + 12/8 + ---- +execute_cmd.c + - execute_coproc: don't warn about an existing coproc if the write and + read file descriptors are unusable (-1), as they will be after a + call to coproc_closeall in a subshell. Fixes spurious warning + reported by Tobias Hoffmann + +jobs.c + - bgp_resize: avoid overflow when calculating the new size if the + child process limit is something ridiculously large. Report and + fix from Natanael Copa + +execute_cmd.c + - execute_builtin_or_function: if we return via the return builtin, we + don't get a chance to free the saved fifo list, so add an unwind- + protect to make sure it happens. Part of fix for leak reported by + Oyvind Hvidsten + - execute_command_internal: if we unwind via the return builtin (e.g., + we execute a function which then returns via the return builtin to + a previous function), we don't free the saved fifo list, so add an + unwind-protect to make sure the free happens. Rest of fix for leak + reported by Oyvind Hvidsten + +subst.c + - add_fifo_list: for the FIFO case (no /dev/fd), make sure we + initialize the new members of the fifo list after xrealloc + + 12/9 + ---- +subst.c + - dev_fd_list: now a list of type `pid_t' so we can store process + associated with the pipe fd into the right element; change all + necessary functions (copy_fifo_list, add_fifo_list) + - process_substitute: store pid of child process into the right + index in dev_fd_list after opening the pipe. Process ID of -1 means + process has been reaped and fd needs to be closed (or FIFO needs to + be unlinked); value of 0 means slot is unused + +jobs.c + - wait_for_background_pids: call reap_procsubs to make sure we clean + up all reaped process substitutions before trying to wait for + everything (still needs work) + +tests/{run-procsub,procsub.{tests,right}} + - new file, tests of process substitution that have failed in the past + + 12/10 + ----- +jobs.c + - wait_for_background_pids: warn if one of the jobs is stopped + +subst.c + - wait_procsubs: new function, call wait_for for every "live" process + substitution + +jobs.c + - wait_for_background_pids: call wait_procsubs to reap any living + process subsitutions diff --git a/MANIFEST b/MANIFEST index 0b66f4b7..e59cb4b0 100644 --- a/MANIFEST +++ b/MANIFEST @@ -929,6 +929,7 @@ tests/cond-regexp2.sub f tests/cond-regexp3.sub f tests/coproc.tests f tests/coproc.right f +tests/coproc1.sub f tests/cprint.tests f tests/cprint.right f tests/dbg-support.right f @@ -1174,6 +1175,8 @@ tests/printf1.sub f tests/printf2.sub f tests/printf3.sub f tests/printf4.sub f +tests/procsub.tests f +tests/procsub.right f tests/quote.tests f tests/quote.right f tests/quote1.sub f @@ -1273,6 +1276,7 @@ tests/run-posixpat f tests/run-posixpipe f tests/run-precedence f tests/run-printf f +tests/run-procsub f tests/run-quote f tests/run-read f tests/run-redir f diff --git a/doc/bash.1 b/doc/bash.1 index 8fc870e4..2fea3513 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -5691,7 +5691,8 @@ or .BR vi . .TP .B emacs\-mode\-string (@) -This string is displayed immediately before the last line of the primary +If the \fIshow\-mode\-in\-prompt\fP variable is enabled, +this string is displayed immediately before the last line of the primary prompt when emacs editing mode is active. The value is expanded like a key binding, so the standard set of meta- and control prefixes and backslash escape sequences is available. @@ -5845,9 +5846,9 @@ a common prefix) cause the matches to be listed immediately instead of ringing the bell. .TP .B show\-mode\-in\-prompt (Off) -If set to \fBOn\fP, add a character to the beginning of the prompt -indicating the editing mode: emacs (@), vi command (:) or vi -insertion (+). +If set to \fBOn\fP, add a string to the beginning of the prompt +indicating the editing mode: emacs, vi command, or vi insertion. +The mode strings are user-settable (e.g., \fIemacs\-mode\-string\fP). .TP .B skip\-completed\-text (Off) If set to \fBOn\fP, this alters the default completion behavior when @@ -5858,7 +5859,8 @@ after point in the word being completed, so portions of the word following the cursor are not duplicated. .TP .B vi\-cmd\-mode\-string ((cmd)) -This string is displayed immediately before the last line of the primary +If the \fIshow\-mode\-in\-prompt\fP variable is enabled, +this string is displayed immediately before the last line of the primary prompt when vi editing mode is active and in command mode. The value is expanded like a key binding, so the standard set of meta- and control prefixes and @@ -5868,7 +5870,8 @@ non-printing characters, which can be used to embed a terminal control sequence into the mode string. .TP .B vi\-ins\-mode\-string ((ins)) -This string is displayed immediately before the last line of the primary +If the \fIshow\-mode\-in\-prompt\fP variable is enabled, +this string is displayed immediately before the last line of the primary prompt when vi editing mode is active and in insertion mode. The value is expanded like a key binding, so the standard set of meta- and control prefixes and diff --git a/execute_cmd.c b/execute_cmd.c index 45bb8758..62835237 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -399,7 +399,7 @@ execute_command (command) #if defined (PROCESS_SUBSTITUTION) /* don't unlink fifos if we're in a shell function; wait until the function returns. */ - if (variable_context == 0) + if (variable_context == 0 && executing_list == 0) unlink_fifo_list (); #endif /* PROCESS_SUBSTITUTION */ @@ -749,6 +749,8 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, { ofifo = num_fifos (); ofifo_list = copy_fifo_list ((int *)&osize); + begin_unwind_frame ("internal_fifos"); + add_unwind_protect (xfree, ofifo_list); saved_fifo = 1; } else @@ -1077,6 +1079,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, if (nfifo > ofifo) close_new_fifos ((char *)ofifo_list, osize); free ((void *)ofifo_list); + discard_unwind_frame ("internal_fifos"); } #endif @@ -2312,7 +2315,7 @@ execute_coproc (command, pipe_in, pipe_out, fds_to_close) /* XXX -- can be removed after changes to handle multiple coprocs */ #if !MULTIPLE_COPROCS - if (sh_coproc.c_pid != NO_PID) + if (sh_coproc.c_pid != NO_PID && (sh_coproc.c_rfd >= 0 || sh_coproc.c_wfd >= 0)) internal_warning (_("execute_coproc: coproc [%d:%s] still exists"), sh_coproc.c_pid, sh_coproc.c_name); coproc_init (&sh_coproc); #endif @@ -4213,11 +4216,13 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close) result = last_command_exit_value; close_pipes (pipe_in, pipe_out); #if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD) +#if 0 /* Close /dev/fd file descriptors in the parent after forking the last child in a (possibly one-element) pipeline. Defer this until any running shell function completes. */ if (pipe_out == NO_PIPE && variable_context == 0) /* XXX */ unlink_fifo_list (); /* XXX */ +#endif #endif command_line = (char *)NULL; /* don't free this. */ bind_lastarg ((char *)NULL); @@ -5097,9 +5102,14 @@ execute_builtin_or_function (words, builtin, var, redirects, char *ofifo_list; #endif -#if defined (PROCESS_SUBSTITUTION) +#if defined (PROCESS_SUBSTITUTION) + begin_unwind_frame ("saved_fifos"); + /* If we return, we longjmp and don't get a chance to restore the old + fifo list, so we add an unwind protect to free it */ ofifo = num_fifos (); ofifo_list = copy_fifo_list (&osize); + if (ofifo_list) + add_unwind_protect (xfree, ofifo_list); #endif if (do_redirections (redirects, RX_ACTIVE|RX_UNDOABLE) != 0) @@ -5178,7 +5188,9 @@ execute_builtin_or_function (words, builtin, var, redirects, nfifo = num_fifos (); if (nfifo > ofifo) close_new_fifos (ofifo_list, osize); - free (ofifo_list); + if (ofifo_list) + free (ofifo_list); + discard_unwind_frame ("saved_fifos"); #endif return (result); @@ -5384,8 +5396,10 @@ parent_return: /* Make sure that the pipes are closed in the parent. */ close_pipes (pipe_in, pipe_out); #if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD) +#if 0 if (variable_context == 0) unlink_fifo_list (); +#endif #endif FREE (command); return (result); diff --git a/jobs.c b/jobs.c index 82e48034..f3d759e1 100644 --- a/jobs.c +++ b/jobs.c @@ -748,7 +748,7 @@ bgp_resize () else nsize = bgpids.nalloc; - while (nsize < js.c_childmax) + while (nsize < (ps_index_t)js.c_childmax) nsize *= 2; if (bgpids.nalloc < js.c_childmax) @@ -2442,7 +2442,10 @@ wait_for_background_pids () itrace("wait_for_background_pids: job %d non-null after js.j_lastj (%d)", i, js.j_lastj); #endif if (jobs[i] && STOPPED (i)) - any_stopped = 1; + { + builtin_warning ("job %d[%d] stopped", i+1, find_last_pid (i, 0)); + any_stopped = 1; + } if (jobs[i] && RUNNING (i) && IS_FOREGROUND (i) == 0) break; @@ -2470,8 +2473,12 @@ wait_for_background_pids () #if defined (PROCESS_SUBSTITUTION) if (last_procsub_child && last_procsub_child->pid != NO_PID) r = wait_for (last_procsub_child->pid); + wait_procsubs (); + reap_procsubs (); #if 1 /* We don't want to wait indefinitely if we have stopped children. */ + /* XXX - should add a loop that goes through the list of process + substitutions and waits for each proc in turn before this code. */ if (any_stopped == 0) { /* Check whether or not we have any unreaped children. */ @@ -3644,11 +3651,12 @@ itrace("waitchld: waitpid returns %d block = %d children_exited = %d", pid, bloc #endif #if defined (PROCESS_SUBSTITUTION) + /* Only manipulate the list of process substitutions while SIGCHLD + is blocked. */ if ((ind = find_procsub_child (pid)) >= 0) set_procsub_status (ind, pid, WSTATUS (status)); /* XXX - save in bgpids list? */ #endif - /* It is not an error to have a child terminate that we did not have a record of. This child could have been part of diff --git a/lib/readline/doc/readline.3 b/lib/readline/doc/readline.3 index 1257cdfa..1cdc4bae 100644 --- a/lib/readline/doc/readline.3 +++ b/lib/readline/doc/readline.3 @@ -6,9 +6,9 @@ .\" Case Western Reserve University .\" chet.ramey@case.edu .\" -.\" Last Change: Fri Feb 3 16:02:47 EST 2017 +.\" Last Change: Thu Dec 7 08:36:25 EST 2017 .\" -.TH READLINE 3 "2017 February 3" "GNU Readline 7.0" +.TH READLINE 3 "2017 December 7" "GNU Readline 7.0" .\" .\" File Name macro. This used to be `.PN', for Path Name, .\" but Sun doesn't seem to like that very much. @@ -439,7 +439,8 @@ or .BR vi . .TP .B emacs\-mode\-string (@) -This string is displayed immediately before the last line of the primary +If the \fIshow\-mode\-in\-prompt\fP variable is enabled, +this string is displayed immediately before the last line of the primary prompt when emacs editing mode is active. The value is expanded like a key binding, so the standard set of meta- and control prefixes and backslash escape sequences is available. @@ -592,9 +593,9 @@ a common prefix) cause the matches to be listed immediately instead of ringing the bell. .TP .B show\-mode\-in\-prompt (Off) -If set to \fBOn\fP, add a character to the beginning of the prompt +If set to \fBOn\fP, add a string to the beginning of the prompt indicating the editing mode: emacs, vi command, or vi insertion. -The mode strings are user-settable. +The mode strings are user-settable (e.g., \fIemacs\-mode\-string\fP). .TP .B skip\-completed\-text (Off) If set to \fBOn\fP, this alters the default completion behavior when @@ -605,7 +606,8 @@ after point in the word being completed, so portions of the word following the cursor are not duplicated. .TP .B vi\-cmd\-mode\-string ((cmd)) -This string is displayed immediately before the last line of the primary +If the \fIshow\-mode\-in\-prompt\fP variable is enabled, +this string is displayed immediately before the last line of the primary prompt when vi editing mode is active and in command mode. The value is expanded like a key binding, so the standard set of meta- and control prefixes and @@ -615,7 +617,8 @@ non-printing characters, which can be used to embed a terminal control sequence into the mode string. .TP .B vi\-ins\-mode\-string ((ins)) -This string is displayed immediately before the last line of the primary +If the \fIshow\-mode\-in\-prompt\fP variable is enabled, +this string is displayed immediately before the last line of the primary prompt when vi editing mode is active and in insertion mode. The value is expanded like a key binding, so the standard set of meta- and control prefixes and diff --git a/lib/readline/doc/rluser.texi b/lib/readline/doc/rluser.texi index 95de21b3..77f1d622 100644 --- a/lib/readline/doc/rluser.texi +++ b/lib/readline/doc/rluser.texi @@ -524,7 +524,8 @@ set to either @samp{emacs} or @samp{vi}. @item emacs-mode-string @vindex emacs-mode-string -This string is displayed immediately before the last line of the primary +If the @var{show-mode-in-prompt} variable is enabled, +this string is displayed immediately before the last line of the primary prompt when emacs editing mode is active. The value is expanded like a key binding, so the standard set of meta- and control prefixes and backslash escape sequences is available. @@ -714,9 +715,9 @@ The default value is @samp{off}. @item show-mode-in-prompt @vindex show-mode-in-prompt -If set to @samp{on}, add a character to the beginning of the prompt +If set to @samp{on}, add a string to the beginning of the prompt indicating the editing mode: emacs, vi command, or vi insertion. -The mode strings are user-settable. +The mode strings are user-settable (e.g., @var{emacs-mode-string}). The default value is @samp{off}. @item skip-completed-text @@ -735,7 +736,8 @@ The default value is @samp{off}. @item vi-cmd-mode-string @vindex vi-cmd-mode-string -This string is displayed immediately before the last line of the primary +If the @var{show-mode-in-prompt} variable is enabled, +this string is displayed immediately before the last line of the primary prompt when vi editing mode is active and in command mode. The value is expanded like a key binding, so the standard set of meta- and control prefixes and @@ -747,7 +749,8 @@ The default is @samp{(cmd)}. @item vi-ins-mode-string @vindex vi-ins-mode-string -This string is displayed immediately before the last line of the primary +If the @var{show-mode-in-prompt} variable is enabled, +this string is displayed immediately before the last line of the primary prompt when vi editing mode is active and in insertion mode. The value is expanded like a key binding, so the standard set of meta- and control prefixes and diff --git a/lib/readline/doc/version.texi b/lib/readline/doc/version.texi index b6222944..470abd51 100644 --- a/lib/readline/doc/version.texi +++ b/lib/readline/doc/version.texi @@ -4,7 +4,7 @@ Copyright (C) 1988-2017 Free Software Foundation, Inc. @set EDITION 7.0 @set VERSION 7.0 -@set UPDATED 28 November 2017 -@set UPDATED-MONTH November 2017 +@set UPDATED 7 December 2017 +@set UPDATED-MONTH December 2017 -@set LASTCHANGE Tue Nov 28 10:14:48 PST 2017 +@set LASTCHANGE Thu Dec 7 08:33:43 EST 2017 diff --git a/nojobs.c b/nojobs.c index 1d00fc96..199fd568 100644 --- a/nojobs.c +++ b/nojobs.c @@ -271,8 +271,11 @@ set_pid_status (pid, status) #if defined (PROCESS_SUBSTITUTION) if ((ind = find_procsub_child (pid)) >= 0) +{ +itrace("waitchld: calling set_procsub_status (%d, %d)", ind, pid); set_procsub_status (ind, pid, WSTATUS (status)); /* XXX - also saving in list below */ +} #endif slot = find_index_by_pid (pid); diff --git a/subst.c b/subst.c index ca9e66a9..8c587622 100644 --- a/subst.c +++ b/subst.c @@ -5251,6 +5251,8 @@ parameter_brace_remove_pattern (varname, value, ind, patstr, rtype, quoted, flag list. NFIFO is a count of the number of FIFOs in the list. */ #define FIFO_INCR 20 +/* PROC value of -1 means the process has been reaped and the FIFO needs to + be removed. PROC value of 0 means the slot is unused. */ struct temp_fifo { char *file; pid_t proc; @@ -5278,11 +5280,19 @@ static void add_fifo_list (pathname) char *pathname; { + int osize, i; + if (nfifo >= fifo_list_size - 1) { + osize = fifo_list_size; fifo_list_size += FIFO_INCR; fifo_list = (struct temp_fifo *)xrealloc (fifo_list, fifo_list_size * sizeof (struct temp_fifo)); + for (i = osize; i < fifo_list_size; i++) + { + fifo_list[i].file = (char *)NULL; + fifo_list[i].proc = 0; /* unused */ + } } fifo_list[nfifo].file = savestring (pathname); @@ -5293,12 +5303,12 @@ void unlink_fifo (i) int i; { - if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1)) + if ((fifo_list[i].proc == (pid_t)-1) || (fifo_list[i].proc > 0 && (kill(fifo_list[i].proc, 0) == -1))) { unlink (fifo_list[i].file); free (fifo_list[i].file); fifo_list[i].file = (char *)NULL; - fifo_list[i].proc = -1; + fifo_list[i].proc = 0; } } @@ -5312,12 +5322,12 @@ unlink_fifo_list () for (i = saved = 0; i < nfifo; i++) { - if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1)) + if ((fifo_list[i].proc == (pid_t)-1) || (fifo_list[i].proc > 0 && (kill(fifo_list[i].proc, 0) == -1))) { unlink (fifo_list[i].file); free (fifo_list[i].file); fifo_list[i].file = (char *)NULL; - fifo_list[i].proc = -1; + fifo_list[i].proc = 0; } else saved++; @@ -5384,7 +5394,7 @@ set_procsub_status (ind, pid, status) int status; { if (ind >= 0 && ind < nfifo) - fifo_list[ind].proc = -2; /* sentinel */ + fifo_list[ind].proc = (pid_t)-1; /* sentinel */ } /* If we've marked the process for this procsub as dead, close the @@ -5395,11 +5405,23 @@ reap_procsubs () int i; for (i = 0; i < nfifo; i++) - if (fifo_list[i].proc == -2) /* reaped */ - { - fifo_list[i].proc = -1; - unlink_fifo (ind); - } + if (fifo_list[i].proc == (pid_t)-1) /* reaped */ + unlink_fifo (i); +} + +void +wait_procsubs () +{ + int i; + + for (i = 0; i < nfifo; i++) + { + if (fifo_list[i].proc != (pid_t)-1 && fifo_list[i].proc > 0) + { + r = wait_for (fifo_list[i].proc); + fifo_list[i].proc = (pid_t)-1; + } + } } int @@ -5436,7 +5458,10 @@ make_named_pipe () has open to children. NFDS is a count of the number of bits currently set in DEV_FD_LIST. TOTFDS is a count of the highest possible number of open files. */ -static char *dev_fd_list = (char *)NULL; +/* dev_fd_list[I] value of -1 means the process has been reaped and file + descriptor I needs to be closed. Value of 0 means the slot is unused. */ + +static pid_t *dev_fd_list = (pid_t *)NULL; static int nfds; static int totfds; /* The highest possible number of open files. */ @@ -5480,8 +5505,8 @@ copy_fifo_list (sizep) if (sizep) *sizep = totfds; - ret = (char *)xmalloc (totfds); - return (memcpy (ret, dev_fd_list, totfds)); + ret = (char *)xmalloc (totfds * sizeof (pid_t)); + return (memcpy (ret, dev_fd_list, totfds * sizeof (pid_t))); } static void @@ -5499,11 +5524,12 @@ add_fifo_list (fd) if (fd >= totfds) totfds = fd + 2; - dev_fd_list = (char *)xrealloc (dev_fd_list, totfds); - memset (dev_fd_list + ofds, '\0', totfds - ofds); + dev_fd_list = (char *)xrealloc (dev_fd_list, totfds * sizeof (dev_fd_list[0])); + /* XXX - might need a loop for this */ + memset (dev_fd_list + ofds, '\0', (totfds - ofds) * sizeof (pid_t)); } - dev_fd_list[fd] = 1; + dev_fd_list[fd] = 1; /* marker; updated later */ nfds++; } @@ -5594,7 +5620,7 @@ set_procsub_status (ind, pid, status) int status; { if (ind >= 0 && ind < totfds) - dev_fd_list[ind] = -2; /* sentinel */ + dev_fd_list[ind] = (pid_t)-1; /* sentinel */ } /* If we've marked the process for this procsub as dead, close the @@ -5605,10 +5631,25 @@ reap_procsubs () int i; for (i = 0; nfds > 0 && i < totfds; i++) - if (dev_fd_list[i] == -2) + if (dev_fd_list[i] == (pid_t)-1) unlink_fifo (i); } +void +wait_procsubs () +{ + int i, r; + + for (i = 0; nfds > 0 && i < totfds; i++) + { + if (dev_fd_list[i] != (pid_t)-1 && dev_fd_list[i] > 0) + { + r = wait_for (dev_fd_list[i]); + dev_fd_list[i] = (pid_t)-1; + } + } +} + #if defined (NOTDEF) print_dev_fd_list () { diff --git a/tests/procsub.right b/tests/procsub.right new file mode 100644 index 00000000..5167c97e --- /dev/null +++ b/tests/procsub.right @@ -0,0 +1,28 @@ +test1 +foo +test2 +test3 +test4 + 8 +test5 +test6 +test7 +test8 +test8a +test9 +hi +bye +l8r +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +intern + 1 + 0 + 0 + 0 + 0 +extern + 1 + 0 + 0 + 0 + 0 diff --git a/tests/procsub.tests b/tests/procsub.tests new file mode 100644 index 00000000..2b60e239 --- /dev/null +++ b/tests/procsub.tests @@ -0,0 +1,93 @@ +# process substitution constructs that have caused problems in the past + +eval cat <(echo test1) +eval "echo foo;cat" <(echo test2) + +unset f +f=<(echo test3); cat "$f" + +unset f +eval f=<(echo test4) "; cat \$f" + +unset f + +FN=$TMPDIR/bashtest-procsub-$$ +cat >"$FN" </dev/null +} +f2(){ + date >/dev/null + cat $1 +} +cat <(echo hi) +f1 <(echo bye) +f2 <(echo l8r) + +unset -f f1 f2 + +moo() { ls -l "$1" >/dev/null; ls -l "$1" >/dev/null; }; moo >(true) +moo() { ls -al "$1" >/dev/null; (true); ls -al "$1" >/dev/null; }; moo >(true) + +unset -f moo + +bug() +{ +c=$(ulimit -n) +let c+=100 +while let c-- +do + while read -ru3 x + do + echo -n : + done 3< <(echo x) +done +echo +} + +bug +unset -f bug + +count_lines() +{ + wc -l < $1 + wc -l < $1 + wc -l < $1 + true | wc -l < $1 + wc -l < $1 +} + +echo intern +count_lines <(date) +unset -f count_lines + +echo extern +FN=$TMPDIR/bashtest-$$ +cat >$FN <&2 +echo "warning: been compiled into the shell or if the OS does not provide" >&2 +echo "warning: /dev/fd." >&2 + +${THIS_SH} ./procsub.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} procsub.right && rm -f ${BASH_TSTOUT}