RE: Q: interoperability of local vars and option nounset
[...] > If your question is whether or not the call to `g' can result > in an unset > variable error even though f has a local copy already > declared, the answer > is no. That is ksh93-style static scoping, and bash does not have it. > Yes, that was my question. Thanks for the answer. I think that for developing scripts it would be helpful to have 'nounset' optionally react on locally unset variables, too. Kind regards Heiko
Bash-4.2 Official Patch 7
BASH PATCH REPORT = Bash-Release: 4.2 Patch-ID: bash42-007 Bug-Reported-by:Matthias Klose Bug-Reference-ID: <4d6fd2ac.1010...@debian.org> Bug-Reference-URL: http://lists.gnu.org/archive/html/bug-bash/2011-03/msg00015.html Bug-Description: When used in contexts where word splitting and quote removal were not performed, such as case statement word expansion, empty strings (either literal or resulting from quoted variables that were unset or null) were not expanded correctly, resulting in failure. Patch (apply with `patch -p0'): *** ../bash-4.2-patched/subst.c 2011-02-25 12:03:58.0 -0500 --- subst.c 2011-03-03 14:08:23.0 -0500 *** *** 4609,4614 --- 4611,4617 if (ifs_firstc == 0) #endif word->flags |= W_NOSPLIT; + word->flags |= W_NOSPLIT2; result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL); expand_no_split_dollar_star = 0; *** ../bash-4.2-patched/patchlevel.hSat Jun 12 20:14:48 2010 --- patchlevel.hThu Feb 24 21:41:34 2011 *** *** 26,30 looks for to find the patch level (for the sccs version string). */ ! #define PATCHLEVEL 6 #endif /* _PATCHLEVEL_H_ */ --- 26,30 looks for to find the patch level (for the sccs version string). */ ! #define PATCHLEVEL 7 #endif /* _PATCHLEVEL_H_ */ -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: [BUG] Bash not reacting to Ctrl-C
> So I don't think my patch is really doing what it _intends_ to do. Let's take a step back and approach this a different way. Instead of trying to intuit whether or not the child did anything with the SIGINT, let's try to make the race condition smaller. The following patch is a very small change to jobs.c that makes wait_sigint_handler only pay attention and set wait_sigint_received when the shell is actually in waitpid() waiting for the child. It uses a semaphore around the call to waitpid to effect that, with a little bookkeeping and cleanup code. When the shell gets a SIGINT while not actually waiting for a child, it restores the old handler and sends SIGINT to itself. Since wait_signal_handler isn't installed if the existing handler is SIG_IGN, this should do the right thing. Please test it and let me know what effect it has. Chet *** ../bash-4.2-patched/jobs.c 2011-01-07 10:59:29.0 -0500 --- jobs.c 2011-03-07 10:40:36.0 -0500 *** *** 2212,2217 --- 2212,2220 #define INVALID_SIGNAL_HANDLER (SigHandler *)wait_for_background_pids static SigHandler *old_sigint_handler = INVALID_SIGNAL_HANDLER; + static int wait_sigint_received; + static int waiting_for_child; + static void restore_sigint_handler () { *** *** 2219,2229 { set_signal_handler (SIGINT, old_sigint_handler); old_sigint_handler = INVALID_SIGNAL_HANDLER; } } - static int wait_sigint_received; - /* Handle SIGINT while we are waiting for children in a script to exit. The `wait' builtin should be interruptible, but all others should be effectively ignored (i.e. not cause the shell to exit). */ --- ,2231 { set_signal_handler (SIGINT, old_sigint_handler); old_sigint_handler = INVALID_SIGNAL_HANDLER; + waiting_for_child = 0; } } /* Handle SIGINT while we are waiting for children in a script to exit. The `wait' builtin should be interruptible, but all others should be effectively ignored (i.e. not cause the shell to exit). */ *** *** 2256,2262 /* XXX - should this be interrupt_state? If it is, the shell will act as if it got the SIGINT interrupt. */ ! wait_sigint_received = 1; /* Otherwise effectively ignore the SIGINT and allow the running job to be killed. */ --- 2258,2271 /* XXX - should this be interrupt_state? If it is, the shell will act as if it got the SIGINT interrupt. */ ! if (waiting_for_child) ! wait_sigint_received = 1; ! else ! { ! last_command_exit_value = 128+SIGINT; ! restore_sigint_handler (); ! kill (getpid (), SIGINT); ! } /* Otherwise effectively ignore the SIGINT and allow the running job to be killed. */ *** *** 2396,2401 --- 2405,2411 if (job_control == 0 || (subshell_environment&SUBSHELL_COMSUB)) { old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler); + waiting_for_child = 0; if (old_sigint_handler == SIG_IGN) set_signal_handler (SIGINT, old_sigint_handler); } *** *** 2524,2529 --- 2534,2542 give_terminal_to (shell_pgrp, 0); } + /* Restore the original SIGINT signal handler before we return. */ + restore_sigint_handler (); + /* If the command did not exit cleanly, or the job is just being stopped, then reset the tty state back to what it was before this command. Reset the tty state and notify *** *** 2589,2595 if (WIFSIGNALED (s) && WTERMSIG (s) == SIGINT && signal_is_trapped (SIGINT) == 0) { UNBLOCK_CHILD (oset); - restore_sigint_handler (); old_sigint_handler = set_signal_handler (SIGINT, SIG_DFL); if (old_sigint_handler == SIG_IGN) restore_sigint_handler (); --- 2602,2607 *** *** 2615,2623 UNBLOCK_CHILD (oset); - /* Restore the original SIGINT signal handler before we return. */ - restore_sigint_handler (); - return (termination_state); } --- 2627,2632 *** *** 3090,3096 --- 3099,3107 waitpid_flags |= WNOHANG; } + waiting_for_child++; pid = WAITPID (-1, &status, waitpid_flags); + waiting_for_child--; /* WCONTINUED may be rejected by waitpid as invalid even when defined */ if (wcontinued && pid < 0 && errno == EINVAL) -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: [BUG] Bash not reacting to Ctrl-C
On Mon, Mar 7, 2011 at 7:52 AM, Chet Ramey wrote: > > Let's take a step back and approach this a different way. Instead of > trying to intuit whether or not the child did anything with the SIGINT, > let's try to make the race condition smaller. I can still easily see the porblem. I think your patch is an improvement over plain bash, but I can still see the problem. How much harder it is to see is hard to say - it's pretty subjective. But I think my patch (the second one, the one that had the "working" EINTR logic) made it _harder_ to trigger than yours does. The trace I just captured looks like this: 08:12:54.424327 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fdf2ad8e9f0) = 15397 08:12:54.424394 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 08:12:54.424432 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 08:12:54.424463 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 08:12:54.424486 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 08:12:54.424510 rt_sigaction(SIGINT, {0x43c990, [], SA_RESTORER, 0x301f833140}, {SIG_DFL, [], SA_RESTORER, 0x301f833140}, 8) = 0 08:12:54.424541 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 15397 08:12:54.424668 --- SIGINT (Interrupt) @ 0 (0) --- 08:12:54.424680 rt_sigreturn(0x2) = 15397 08:12:54.424702 rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x301f833140}, {0x43c990, [], SA_RESTORER, 0x301f833140}, 8) = 0 08:12:54.424739 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 08:12:54.424761 --- SIGCHLD (Child exited) @ 0 (0) --- 08:12:54.424772 wait4(-1, 0x7fff0a9956dc, WNOHANG, NULL) = -1 ECHILD (No child processes) 08:12:54.424793 rt_sigreturn(0x) = 0 08:12:54.424824 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 08:12:54.424850 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 08:12:54.424881 rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0 and I think one reason why the race is hard to get rid of is simply that system call return is _the_ common point of signal handling in UNIX (technically, obviously any return to user space, but there are no appreciable interrupts etc going on, and there _are_ a lot of system calls). The above trace is one that my patch would have handled correctly (it has no EINTR). And there aren't a lot of different system calls in the tight loop here: that's literally the whole loop of the "while : ; do /bin/true; done" thing. So most of the time, SIGINT will happen at _one_ of those system calls, and so even if you set that "waiting_for_child" flag right around the call to "wait4()", the race is actually much easier to hit than you'd think from "it's just a few CPU instructions". So the above trace is one that my patch would have handled correctly (since it has no EINTR). Maybe a combination of the two approaches would work even better? Linus
Re: [BUG] Bash not reacting to Ctrl-C
On 03/07, Chet Ramey wrote: > > > So I don't think my patch is really doing what it _intends_ to do. > > Let's take a step back and approach this a different way. Instead of > trying to intuit whether or not the child did anything with the SIGINT, > let's try to make the race condition smaller. OK, I'll try to test this patch later to see if it make the difference... At least the subjective difference. But, > The following patch is a very small change to jobs.c that makes > wait_sigint_handler only pay attention and set wait_sigint_received when > the shell is actually in waitpid() waiting for the child. It uses a > semaphore around the call to waitpid to effect that, with a little > bookkeeping and cleanup code. When the shell gets a SIGINT while not > actually waiting for a child, it restores the old handler and sends > SIGINT to itself. Hmm. It is very possible I do not understand the patch correctly. But doesn't this patch introduce another problem? > *** 3090,3096 > --- 3099,3107 > waitpid_flags |= WNOHANG; > } > > + waiting_for_child++; > pid = WAITPID (-1, &status, waitpid_flags); OK, and what if ^C comes before waiting_for_child++ ? IIUC, in this case bash exits and leaves the current application (say, emacs which threats SIGINT specially) alone, no? Oleg.
Re: [BUG] Bash not reacting to Ctrl-C
On Mon, Mar 7, 2011 at 8:24 AM, Linus Torvalds wrote: > > and I think one reason why the race is hard to get rid of is simply > that system call return is _the_ common point of signal handling in > UNIX (technically, obviously any return to user space, but there are > no appreciable interrupts etc going on, and there _are_ a lot of > system calls). The above trace is one that my patch would have handled > correctly (it has no EINTR). Linux also ends up making this race easier to see probably because all system calls that are interruptible by signals are all "greedy": they try to do as much real work as possible, rather than return EINTR. That means that if there is work pending (like characters in a tty buffer for "read()", or a child that has exited for "wait()"), then system calls under Linux (and likely all other Unixes too, but Linux is the one I can guarantee works this way) will always do as much real work as possible, and return that real work rather than return with EINTR. So the _common_ case will be: - the system call returns with success ("read a few characters" or "found this child") - but the signal handler will be executed immediately at the return point, so user space won't really even "see" the success before the signal handler is executed. In other words, when you do waiting_for_child++; pid = WAITPID (-1, &status, waitpid_flags); waiting_for_child--; even if the "waiting_for_child--" were to be compiled to be one single instruction, and at the exact return point of the system call, the signal handler would still happen right in between the system call return and that instruction. Linus
Re: [BUG] Bash not reacting to Ctrl-C
> The trace I just captured looks like this: > > 08:12:54.424327 clone(child_stack=0, > flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, > child_tidptr=0x7fdf2ad8e9f0) = 15397 > 08:12:54.424394 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 > 08:12:54.424432 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 > 08:12:54.424463 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 > 08:12:54.424486 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 > 08:12:54.424510 rt_sigaction(SIGINT, {0x43c990, [], SA_RESTORER, > 0x301f833140}, {SIG_DFL, [], SA_RESTORER, 0x301f833140}, 8) = 0 > 08:12:54.424541 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], > 0, NULL) = 15397 > 08:12:54.424668 --- SIGINT (Interrupt) @ 0 (0) --- > 08:12:54.424680 rt_sigreturn(0x2) = 15397 > 08:12:54.424702 rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, > 0x301f833140}, {0x43c990, [], SA_RESTORER, 0x301f833140}, 8) = 0 > 08:12:54.424739 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 > 08:12:54.424761 --- SIGCHLD (Child exited) @ 0 (0) --- > 08:12:54.424772 wait4(-1, 0x7fff0a9956dc, WNOHANG, NULL) = -1 ECHILD > (No child processes) > 08:12:54.424793 rt_sigreturn(0x) = 0 > 08:12:54.424824 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 > 08:12:54.424850 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 > 08:12:54.424881 rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0 > > and I think one reason why the race is hard to get rid of is simply > that system call return is _the_ common point of signal handling in > UNIX (technically, obviously any return to user space, but there are > no appreciable interrupts etc going on, and there _are_ a lot of > system calls). The above trace is one that my patch would have handled > correctly (it has no EINTR). The one thing that jumps out at me here is the number of signal-handling system calls. wait_sigint_handler gets installed and removed as the SIGINT handler a lot. I wonder if we would see an improvement if I used a global SIGINT handler that understood what to do with wait_sigint_received. That's a change for down the road. > And there aren't a lot of different system calls in the tight loop > here: that's literally the whole loop of the "while : ; do /bin/true; > done" thing. So most of the time, SIGINT will happen at _one_ of those > system calls, and so even if you set that "waiting_for_child" flag > right around the call to "wait4()", the race is actually much easier > to hit than you'd think from "it's just a few CPU instructions". > > So the above trace is one that my patch would have handled correctly > (since it has no EINTR). Maybe a combination of the two approaches > would work even better? I think we're eventually going to converge on a hybrid solution. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: [BUG] Bash not reacting to Ctrl-C
> On 03/07, Chet Ramey wrote: > > > > > So I don't think my patch is really doing what it _intends_ to do. > > > > Let's take a step back and approach this a different way. Instead of > > trying to intuit whether or not the child did anything with the SIGINT, > > let's try to make the race condition smaller. > > OK, I'll try to test this patch later to see if it make the difference... > At least the subjective difference. > > But, > > > The following patch is a very small change to jobs.c that makes > > wait_sigint_handler only pay attention and set wait_sigint_received when > > the shell is actually in waitpid() waiting for the child. It uses a > > semaphore around the call to waitpid to effect that, with a little > > bookkeeping and cleanup code. When the shell gets a SIGINT while not > > actually waiting for a child, it restores the old handler and sends > > SIGINT to itself. > > Hmm. It is very possible I do not understand the patch correctly. > > But doesn't this patch introduce another problem? > > > *** 3090,3096 > > --- 3099,3107 > > waitpid_flags |= WNOHANG; > > } > > > > + waiting_for_child++; > > pid = WAITPID (-1, &status, waitpid_flags); > > OK, and what if ^C comes before waiting_for_child++ ? > > IIUC, in this case bash exits and leaves the current application > (say, emacs which threats SIGINT specially) alone, no? Yes, it does. However, the same problem exists now. There is a window between the time bash forks, the child execs, and bash waits when a SIGINT can arrive and the same thing will happen. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: [BUG] Bash not reacting to Ctrl-C
On Mon, Mar 7, 2011 at 8:45 AM, Chet Ramey wrote: > > The one thing that jumps out at me here is the number of signal-handling > system calls. wait_sigint_handler gets installed and removed as the > SIGINT handler a lot. I wonder if we would see an improvement if I > used a global SIGINT handler that understood what to do with > wait_sigint_received. That's a change for down the road. Signal handling is a pain. There's a reason people hate UNIX signals. It's damn well nearly impossible to handle signals well and without races. Many server applications in particular end up basically exposing them as synchronous events rather than as signals, and it's why we have all the crazy "pselect()" etc extensions to various waiting system calls to say "I want to wait for events and still be interrupted by signals, but I want to then actually *handle* the signal synchronously". And they often do it for efficiency reasons - exactly so that they can avoid the cost of blocking and unblocking them all the time around critical regions. But even if there was some "pwait()" system call interface, I don't think it would really help this particular problem. You might be able to avoid a system call or two (and that would look prettier in traces), and some things might be faster (which is why the server people do it) and might be easier to understand (asynchronous events are just painful as hell). But the fundamental issue is still simply that the whole situation is ambiguous. It really isn't possible to tell the difference between "somebody blocked SIGINT and then returned success later _despite_ the SIGINT" and "somebody returned successfully before SIGINT even happened". Except for timing. The "catch EINTR" was a try at catching a timing issue: "did we see the dead child before we saw the SIGINT". And I think it's why it works pretty well (I really had to do quite a lot of testing to catch the lost ^C behavior with that patch - in contrast, with your latest patch I think I caught it on the fifth or sixth try). Painful. Linus
Re: [BUG] Bash not reacting to Ctrl-C
On 03/07, Chet Ramey wrote: > > > On 03/07, Chet Ramey wrote: > > > > > > *** 3090,3096 > > > --- 3099,3107 > > > waitpid_flags |= WNOHANG; > > > } > > > > > > + waiting_for_child++; > > > pid = WAITPID (-1, &status, waitpid_flags); > > > > OK, and what if ^C comes before waiting_for_child++ ? > > > > IIUC, in this case bash exits and leaves the current application > > (say, emacs which threats SIGINT specially) alone, no? > > Yes, it does. However, the same problem exists now. There is a window > between the time bash forks, the child execs, and bash waits when a SIGINT > can arrive and the same thing will happen. OK... I seem to understand make_child() blocks SIGINT, but at this point the signal handler is SIG_DFL. And then it forks and unblocks the signal without installing the handler. Thanks. I am just curious, is this another bug/problem or this was intended? Oleg.
How to safely pipe output to tee?
I want to compute a command string which will end up in foo. Then I want to run that command and cause stdout and stderr to be piped to tee for safe keeping while it also goes to the screen. After the command finishes, I need tee to exit. It sounds easy, but it's not. eval "$foo" 2>&1 | tee filename will cause a hang. Why? Because what $foo does is to start lots of child processes and services which do not end. I just want to proceed to the next command as soon as $foo completes. I have the Kudge O The Day currently running, but I'd love to see something better. My current setup is this: mkfifo fifoname tee filename < fifoname & teepid=$! eval "$foo" > fifoname 2>&1 kill $teepid rm fifoname And also, BTW, I do need the exit status of the executed command. Anyone have a better idea? TIA -- Time flies like the wind. Fruit flies like a banana. Stranger things have .0. happened but none stranger than this. Does your driver's license say Organ ..0 Donor?Black holes are where God divided by zero. Listen to me! We are all- 000 individuals! What if this weren't a hypothetical question? steveo at syslang.net
Re: How to safely pipe output to tee?
(03/07/2011 10:31 AM), Steven W. Orr wrote: > I want to compute a command string which will end up in foo. > > Then I want to run that command and cause stdout and stderr to be piped > to tee for safe keeping while it also goes to the screen. > > After the command finishes, I need tee to exit. > > It sounds easy, but it's not. > > eval "$foo" 2>&1 | tee filename > > will cause a hang. Why? Because what $foo does is to start lots of child > processes and services which do not end. I just want to proceed to the > next command as soon as $foo completes. It seems to me that tee hangs around because its pipe is still open on the other end (courtesy of these background processes you mention). In that case, can't you just redirect all these background processes, so that they're not writing to that same stdout file descriptor? For instance, foo='sleep 100 &' poses an issue, but foo='sleep 100 >&- 2>&- &' shouldn't. -- HTH, Micah J. Cowan http://micah.cowan.name/
Re: How to safely pipe output to tee?
On 3/7/2011 2:02 PM, Micah Cowan wrote: (03/07/2011 10:31 AM), Steven W. Orr wrote: I want to compute a command string which will end up in foo. Then I want to run that command and cause stdout and stderr to be piped to tee for safe keeping while it also goes to the screen. After the command finishes, I need tee to exit. It sounds easy, but it's not. eval "$foo" 2>&1 | tee filename will cause a hang. Why? Because what $foo does is to start lots of child processes and services which do not end. I just want to proceed to the next command as soon as $foo completes. It seems to me that tee hangs around because its pipe is still open on the other end (courtesy of these background processes you mention). In that case, can't you just redirect all these background processes, so that they're not writing to that same stdout file descriptor? For instance, foo='sleep 100&' poses an issue, but foo='sleep 100>&- 2>&-&' shouldn't. Sorry, but I'm not sure I see why this helps. I think it says (I assume you meant a space between the 100 and the greater than, otherwise you're just trying to close channel 100): foo='sleep 100 >&- 2>&- &' "Sleep for 100 seconds and then close channel 1 and channel 2." Maybe. But how do I harvest the status of the command, since the sleep will always succeed? -- Time flies like the wind. Fruit flies like a banana. Stranger things have .0. happened but none stranger than this. Does your driver's license say Organ ..0 Donor?Black holes are where God divided by zero. Listen to me! We are all- 000 individuals! What if this weren't a hypothetical question? steveo at syslang.net
Re: How to safely pipe output to tee?
On Mon, Mar 07, 2011 at 03:22:26PM -0500, Steven W. Orr wrote: > foo='sleep 100 >&- 2>&- &' > > "Sleep for 100 seconds and then close channel 1 and channel 2." No. Redirections are done first.
Re: How to safely pipe output to tee?
(03/07/2011 12:22 PM), Steven W. Orr wrote: > Sorry, but I'm not sure I see why this helps. > > I think it says (I assume you meant a space between the 100 and the > greater than, otherwise you're just trying to close channel 100): > > foo='sleep 100 >&- 2>&- &' Yeah. That's how I typed it. Your mailer seems to have screwed it up, because mine shows the original like that. > "Sleep for 100 seconds and then close channel 1 and channel 2." No. Sleep for 100 seconds, immediately closing channel 1 and channel 2 for that program ("sleep 100" just represents an arbitrary program to background). > Maybe. But how do I harvest the status of the command, since the sleep > will always succeed? The example was meant to show what to do with the background processes you said you spawn. You obviously can't harvest the statuses of processes that haven't actually exited yet. I assumed you meant the status of the overall "foo" command. The central idea is that you make sure that any background processes don't keep the pipe open. So the general pattern is: foo='arbitrary-foo-commands; bkgnd-procA >&- 2>&- & \ bkgnd-procB >&- 2>&- & more-arbitrary-foo-commands' (If your mail-reader screws that up too, then you'll have to adjust... maybe see if looking at the mail's source improves matters) Then, evaluating foo will return the final exit status (from the final command), while the background processes will be prevented from writing to the pipe (which will be closed when foo exits). (Note, by the way, that the 2>&- bits are only necessary because you did 2>&1 on your eval.) I don't know whether your "real" foo gives you that level of control over what you do with your background tasks; so long as you can control their output descriptors, you can do something along these lines (which is really the proper way to deal with this issue). If you do not have that level of control over them, then there won't be any better way (that I can think of) than your current solution. If, for instance, your foo is something like "mydaemon -d", where it does some cursory error-checking, and then if everything seems fine, spawns to the background, then your ability to do what you want is limited. The only real salvation is if "mydaemon" has a "-q" option that not only prevents output except in cases of error, but actually causes it to close its stdout and stderr so that the pipe no longer has a writer. -- Micah J. Cowan http://micah.cowan.name/
variable name and its' value are the same characters causes recursion error
Hi Chet, Summary *** When a variable name and its' value are the same characters (a="a"), a recursion error occurs. Steps to recreate "problem" *** Step 1: 1. Execute the command . a="cat";b="dog";[[ $a -lt $b ]]; echo $? 1 . Step 2: 1. Change a="cat" to a="a". 2. Execute the command . a="a";b="dog";[[ $a -lt $b ]]; echo $? bash: [[: a: expression recursion level exceeded (error token is "a") 1 . In the steps above, I know I am using the numeric operator -lt to compare 2 strings, in [[]]. But a recursion error seems a little harsh, and seems inconsistent between Step 1's results and Step 2's. The recursion error does not occur in Step 1, but it does in Step 2. The only thing that changed was a="cat" to a="a". On the other hand, if it is a usage error, which [] considers it to be, shouldn't the return status be 2, not 1. Occurs in the following *** - GNU bash, version 4.0.35(1)-release (x86_64-suse-linux-gnu) - GNU bash, version 4.2.0(1)-release (x86_64-suse-linux-gnu) - OpenSuSE 11.2 Additional Info *** I came across the above when I was running through the scenarios below to better understand tests, evaluation, and return codes/exit status. .-+.---. | || Return Codes | |Expression | Evaluates'---.---' | (a=5; unset b) || True | False | | || Succ | Failu | '-++---+---' | date|| 0 | - | | date -a 2>/dev/null || - | 1 | '-++---+---' | (( a )) | 5 (^1) | 0 | - | | (( a < 4 )) | 5 < 4 (^1) | - | 1 | | (( a < a-1 )) | 5 < 5-1 (^1) | - | 1 | '-++---+---' | (( $a ))| 5 (^1) | 0 | - | | (( $a < 4 ))| 5 < 4 (^1) | - | 1 | | (( $a < $a-1 )) | 5 < 5-1 (^1) | - | 1 | '-++---+---' | [[ $a ]]| 5 (^2) | 0 | - | | [[ $a -lt 4 ]] | 5 < 4 | - | 1 | | [[ $a < 4 ]]| 5 < 4 | - | 1 | '-++---+---' | (( b )) | '' (^2)| - | 1 | | (( $b ))| '' (^2)| - | 1 | | [[ $b ]]| '' (^2)| - | 1 | '-++---+---' | [[ a ]] | a (^3) | 0 | - | | [[ b ]] | b (^3 | 0 | - | | || - | - | | || - | - | | || - | - | | || - | - | '-''---'---' (1) If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. (2) The only variable regarded as false is unset or value is null. (3) The (bare)word expands into word, which is neither null or unset, but rather the word itself. [NOTE] = - The execution of a command or program is expected to return an error status integer, which will be 0 (true) if the program completes successfully, and nonzero (false) if an error occurs. * EXIT_SUCCESS = 0 * EXIT_FAILURE = non-zero value - When using compound commands, the exit status of 0 and nonzero still stands, but there is an intermediary step that deals with how conditional and arithmetic expressions are evaluated. - Arithmetic Evaluation ((...)): Within an expression, shell variables may be referenced by name without using the parameter expansion syntax. = Thank you. Peggy Russell
no local bash_history created or written to if existing (~/.bash_history
with the current bash used in ubuntu 11.04 there no longer is a ~/.bash_history created If there is an existing ~/.bash_history in place or one is inadvertently created, *see below, then it will not be written to If one was to crash the system while a command was running in a terminal then a ~/.bash_history would be created if not already and the running command would be saved to it. That is the only way commands are saved to the history or the file created in the absence of pre-existing one Machine: i686 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='i686' -DCONF_OSTYPE='lin$ uname output: Linux doug-XPS-M1330 2.6.38-5-generic #32-Ubuntu SMP Tue Feb 22 1$ Machine Type: i686-pc-linux-gnu Bash Version: 4.2 Patch Level: 6 Release Status: release This is not limited to just 11.04 current unattended launchpad bug https://bugs.launchpad.net/ubuntu/+source/bash/+bug/725327
Re: [BUG] Bash not reacting to Ctrl-C
On 3/7/11 12:42 PM, Oleg Nesterov wrote: > On 03/07, Chet Ramey wrote: >> >>> On 03/07, Chet Ramey wrote: *** 3090,3096 --- 3099,3107 waitpid_flags |= WNOHANG; } + waiting_for_child++; pid = WAITPID (-1, &status, waitpid_flags); >>> >>> OK, and what if ^C comes before waiting_for_child++ ? >>> >>> IIUC, in this case bash exits and leaves the current application >>> (say, emacs which threats SIGINT specially) alone, no? >> >> Yes, it does. However, the same problem exists now. There is a window >> between the time bash forks, the child execs, and bash waits when a SIGINT >> can arrive and the same thing will happen. > > OK... I seem to understand make_child() blocks SIGINT, but at this > point the signal handler is SIG_DFL. And then it forks and unblocks the > signal without installing the handler. > > Thanks. I am just curious, is this another bug/problem or this was > intended? Intended. The SIGINT gets blocked so the internal state doesn't get messed up (and we want the fork to complete). The wait signal handler is only for when we're actually waiting for the child. (And it's not always SIGDFL -- this same code path is executed by interactive shells, too.) While it is a race condition, this one's really, really hard to hit. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: [BUG] Bash not reacting to Ctrl-C
On 3/7/11 11:52 AM, Linus Torvalds wrote: > On Mon, Mar 7, 2011 at 8:24 AM, Linus Torvalds > wrote: >> >> and I think one reason why the race is hard to get rid of is simply >> that system call return is _the_ common point of signal handling in >> UNIX (technically, obviously any return to user space, but there are >> no appreciable interrupts etc going on, and there _are_ a lot of >> system calls). The above trace is one that my patch would have handled >> correctly (it has no EINTR). > > Linux also ends up making this race easier to see probably because all > system calls that are interruptible by signals are all "greedy": they > try to do as much real work as possible, rather than return EINTR. Yes, the BSDs have traditionally behaved this way as well. I just had a much harder time reproducing this on FreeBSD-derived Mac OS X. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: variable name and its' value are the same characters causes recursion error
On 3/6/11 3:13 PM, Peggy Russell wrote: > Hi Chet, > > Summary > *** > When a variable name and its' value are the same characters (a="a"), > a recursion error occurs. Quite true. If you expand the problem expression, you get [[ a -lt b ]] Since those are not numeric, bash treats them as expressions to be evaluated. You don't have to use the $ to obtain variable evaluation when using [[ or [. You get: [[ a -lt b ]] which bash treats as expressions to be evaluated, since they're not numeric. And so on. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: no local bash_history created or written to if existing (~/.bash_history
On 3/6/11 2:53 PM, Doug McMahon wrote: > with the current bash used in ubuntu 11.04 there no longer is a > ~/.bash_history created > If there is an existing ~/.bash_history in place or one is inadvertently > created, *see below, then it will not be written to Demonstrably false: (1)$ ./bash (2)$ HISTFILE=history (2)$ echo $BASH_VERSION 4.2.7(3)-maint (2)$ echo a a (2)$ exit exit (1)$ cat history HISTFILE=history echo $BASH_VERSION echo a exit One thing that has changed is that an interactive shell will no longer attempt to write the history file if it's killed by a signal, since that causes many functions to be executed that are not safe to call from a signal handler. If you're in the habit of trying to exit the shell by closing the terminal window, which causes the shell to be killed by SIGHUP (I think, maybe SIGTERM), the history will not be saved. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: variable name and its' value are the same characters causes recursion error
> Since those are not numeric, bash treats them as expressions to be > evaluated. You don't have to use the $ to obtain variable evaluation > when using [[ or [. You get: c=1;a="c";b=2;[[ a -lt b ]]; echo $? 0 c=3;a="c";b=2;[[ a -lt b ]]; echo $? 1 I see. I was aware of explicit indirection as described in the man page section "Parameter Expansion", with the syntax ${!name}. I wasn't aware of the above implicit indirection with [[ expression ]]. But, for [ expression ], I have to use explicit indirection with ${!a} otherwise I get an error, "bash: [: a: integer expression expected". This brings up some interesting situations with indirection and declare: # f is assigned the value of z through implicit indirection unset z f;declare -i z=5;declare -i f="z";declare -p z f declare -i z="5" declare -i f="5" # f is assigned the default value of 0 when z is not defined # for implicit indirection unset z f;declare -i f="z";declare -p z f bash: declare: z: not found declare -i f="0" # f is assigned the default value of 0 when empty variable name # is used for implicit indirection unset z f;declare -i f="";declare -p z f bash: declare: z: not found declare -i f="0" # unset z f;declare -i f;echo $?;echo \"$f\";declare -p z f 0 "" bash: declare: z: not found bash: declare: f: not found It would be helpful if indirection was explained in the documentation for [[ expression ]], [ expression ], and declare. Thank you. Peg