From eed646cc6091fc9c81294120b02cb932c85f8118 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Tue, 31 May 2022 09:55:01 -0400 Subject: [PATCH] fix race condition in builtins Makefile --- CWRU/CWRU.chlog | 20 ++++++++++++++++++++ builtins/Makefile.in | 32 +++++++++++++++++--------------- builtins/mkbuiltins.c | 19 +++++++++++++++---- examples/scripts/bcalc | 17 +++++++++++++++++ execute_cmd.c | 3 --- 5 files changed, 69 insertions(+), 22 deletions(-) diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 66176267..8de59b64 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -3624,3 +3624,23 @@ builtins/suspend.def doc/{bash.1,bashref.texi} - suspend: updated description to include expanded -f behavior + + 5/25 + ---- +builtins/mkbuiltins.c + - -includefile: new argument, specifies extern filename to insert + into the #include statement in the structfile (builtins.c) and + the filename in the comment in the extern file (builtext.h). + From Alexander Kanavin via + https://savannah.gnu.org/patch/?10210 + +builtins/Makefile.in + - builtins.c: change call to mkbuiltins to add -includefile option + - builtins.c: change recipe to run all the commands in the same shell + invocation + - builtins.c: change recipe to specify new filenames in the call to + mkbuiltins and move them onto builtins.c/builtext.h if the new ones + are different; make the new filenames use the current make recipe + shell pid in the filename ($$RECPID). + Inspired by Alexander Kanavin via + https://savannah.gnu.org/patch/?10210 diff --git a/builtins/Makefile.in b/builtins/Makefile.in index 313ea54f..642878c6 100644 --- a/builtins/Makefile.in +++ b/builtins/Makefile.in @@ -1,6 +1,6 @@ # This Makefile for building libbuiltins.a is in -*- text -*- for Emacs. # -# Copyright (C) 1996-2021 Free Software Foundation, Inc. +# Copyright (C) 1996-2022 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -186,20 +186,22 @@ gen-helpfiles: tmpbuiltins.o gen-helpfiles.o $(CC_FOR_BUILD) $(LDFLAGS_FOR_BUILD) -o $@ gen-helpfiles.o tmpbuiltins.o $(LIBS_FOR_BUILD) builtext.h builtins.c: $(MKBUILTINS) $(DEFSRC) - @-if test -f builtins.c; then mv -f builtins.c old-builtins.c; fi - @-if test -f builtext.h; then mv -f builtext.h old-builtext.h; fi - ./$(MKBUILTINS) -externfile builtext.h -structfile builtins.c \ - -noproduction $(DIRECTDEFINE) $(HELPDIRDEFINE) $(HELPSTRINGS) $(DEFSRC) - @-if cmp -s old-builtext.h builtext.h 2>/dev/null; then \ - mv old-builtext.h builtext.h; \ - else \ - $(RM) old-builtext.h; \ - fi - @-if cmp -s old-builtins.c builtins.c 2>/dev/null; then \ - mv old-builtins.c builtins.c; \ - else \ - $(RM) old-builtins.c; \ - fi + @RECPID=$$$$ ; \ + NEW_BUILTEXT=builtext-$$RECPID.h NEW_BUILTINS=builtins-$$RECPID.c ; \ + ./$(MKBUILTINS) -externfile $$NEW_BUILTEXT \ + -includefile builtext.h \ + -structfile $$NEW_BUILTINS \ + -noproduction $(DIRECTDEFINE) $(HELPDIRDEFINE) $(HELPSTRINGS) $(DEFSRC) ; \ + if cmp -s $$NEW_BUILTEXT builtext.h 2>/dev/null; then \ + $(RM) $$NEW_BUILTEXT; \ + else \ + mv $$NEW_BUILTEXT builtext.h; \ + fi ; \ + if cmp -s $$NEW_BUILTINS builtins.c 2>/dev/null; then \ + $(RM) $$NEW_BUILTINS ; \ + else \ + mv $$NEW_BUILTINS builtins.c; \ + fi helpdoc: gen-helpfiles ./gen-helpfiles ${HELPDIRDEFINE} diff --git a/builtins/mkbuiltins.c b/builtins/mkbuiltins.c index f21b76b9..f505ebde 100644 --- a/builtins/mkbuiltins.c +++ b/builtins/mkbuiltins.c @@ -1,7 +1,7 @@ /* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from a single source file called builtins.def. */ -/* Copyright (C) 1987-2021 Free Software Foundation, Inc. +/* Copyright (C) 1987-2022 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -113,6 +113,12 @@ char *struct_filename = (char *)NULL; /* The name of the external declaration file. */ char *extern_filename = (char *)NULL; +/* The name of the include file to write into the structure file, if it's + different from extern_filename. */ +char *include_filename = (char *)NULL; + +/* The name of the include file to put into the generated struct filename. */ + /* Here is a structure for manipulating arrays of data. */ typedef struct { int size; /* Number of slots allocated to array. */ @@ -241,6 +247,8 @@ main (argc, argv) if (strcmp (arg, "-externfile") == 0) extern_filename = argv[arg_index++]; + else if (strcmp (arg, "-includefile") == 0) + include_filename = argv[arg_index++]; else if (strcmp (arg, "-structfile") == 0) struct_filename = argv[arg_index++]; else if (strcmp (arg, "-noproduction") == 0) @@ -284,6 +292,9 @@ main (argc, argv) } } + if (include_filename == 0) + include_filename = extern_filename; + /* If there are no files to process, just quit now. */ if (arg_index == argc) exit (0); @@ -1125,7 +1136,7 @@ char *structfile_header[] = { "/* This file is manufactured by ./mkbuiltins, and should not be", " edited by hand. See the source to mkbuiltins for details. */", "", - "/* Copyright (C) 1987-2021 Free Software Foundation, Inc.", + "/* Copyright (C) 1987-2022 Free Software Foundation, Inc.", "", " This file is part of GNU Bash, the Bourne Again SHell.", "", @@ -1187,7 +1198,7 @@ write_file_headers (structfile, externfile) fprintf (structfile, "%s\n", structfile_header[i]); fprintf (structfile, "#include \"%s\"\n", - extern_filename ? extern_filename : "builtext.h"); + include_filename ? include_filename : "builtext.h"); fprintf (structfile, "#include \"bashintl.h\"\n"); @@ -1197,7 +1208,7 @@ write_file_headers (structfile, externfile) if (externfile) fprintf (externfile, "/* %s - The list of builtins found in libbuiltins.a. */\n", - extern_filename ? extern_filename : "builtext.h"); + include_filename ? include_filename : "builtext.h"); } /* Write out any necessary closing information for diff --git a/examples/scripts/bcalc b/examples/scripts/bcalc index e88dcfca..bc7e2b40 100644 --- a/examples/scripts/bcalc +++ b/examples/scripts/bcalc @@ -34,14 +34,30 @@ init() coproc BC { bc -q 2>&1; } # set scale printf "scale = 10\n" >&${BC[1]} + # bash automatically sets BC_PID to the coproc pid; we store it so we + # can be sure to use it even after bash reaps the coproc and unsets + # the variables + coproc_pid=$BC_PID } # not strictly necessary; the pipes will be closed when the program exits +# but we can use it in reset() below fini() { eval exec "${BC[1]}>&- ${BC[0]}<&-" } +reset() +{ + fini # close the old pipes + + sleep 1 + kill -1 $coproc_pid >/dev/null 2>&1 # make sure the coproc is dead + unset coproc_pid + + init +} + # set a read timeout of a half second to avoid synchronization problems calc() { @@ -71,6 +87,7 @@ do case "$EQN" in '') continue ;; exit|quit) break ;; + reset) reset ; continue ;; esac # save to the history list diff --git a/execute_cmd.c b/execute_cmd.c index 8a486e26..dd35c7d1 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -2515,9 +2515,6 @@ execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close) prev = pipe_in; cmd = command; -if (asynchronous) - itrace("execute_pipeline: asynchronous = 1"); - while (cmd && cmd->type == cm_connection && cmd->value.Connection && cmd->value.Connection->connector == '|') {