On Fri, Aug 13, 2010 at 12:18:23PM +0200, Werner Fink wrote:
> On Thu, Aug 12, 2010 at 05:37:55PM -0500, lstee...@gmail.com wrote:
> > #!/bin/bash
> > #
> > # A script to test PIPESTATUS and pipefail
> > #
> > echo " cmd: set +o pipefail"
> > echo " pipe: ps -ef 2>&1 | grep "^\$USR" >/dev/null"
> > set +o pipefail
> > ps -ef 2>&1 | grep "^$USR" >/dev/null
> > echo "expect: PIPESTATUS = 1 0 \$? = 0; got: PIPESTATUS = ${PIPESTATUS[*]}
> > \$? = $?"
> > echo
> > echo " cmd: set -o pipefail"
> > echo " pipe: ps -ef 2>&1 | grep "^\$USR" >/dev/null"
> > set -o pipefail
> > ps -ef 2>&1 | grep "^$USR" >/dev/null
> > echo "expect: PIPESTATUS = 1 0 \$? = 1; got: PIPESTATUS = ${PIPESTATUS[*]}
> > \$? = $?"
> > echo
> > echo " pipe: ps aux 2>&1 | grep "^\$USER" >/dev/null"
> > ps aux 2>&1 | grep "^$USER" >/dev/null
> > echo "expect: PIPESTATUS = 0 0 \$? = 0; got: PIPESTATUS = ${PIPESTATUS[*]}
> > \$? = $?"
> > echo "expect: PIPESTATUS = 0 \$? = 0; got: PIPESTATUS = ${PIPESTATUS[*]}
> > \$? = $?"
> > #
> > # End of script
> >
> > None of the 'got' results 'expect'ing multiple PIPESTATUS results work.
>
> Question: could it be that you're using the bash from
> http://download.opensuse.org/repositories/shells/ or
> http://download.opensuse.org/factory/ ?
>
> Then you may see a side effect of the patch enabling that a pipe uses
> only subshells left from that last pipe symbol. This makes things
> work like
>
> bash> echo 1 2 | read a b; echo $a $b
> 1 2
>
> ... please report such problems on the channels for opensuse.org.
>
> Sorry Chet for the noise
The attached patch should do a better job, nevertheless IMHO there
could be a better solution. This could require some more work
on the COMMAND API to avoid things like
add_process((char*)0, getpid());
in execute_cmd.c, also the addjstatus() function is more like
a workaround to get the status back into the JOB/PROCESS API.
Werner
--
"Having a smoking section in a restaurant is like having
a peeing section in a swimming pool." -- Edward Burr
--- command.h
+++ command.h 2010-08-13 16:48:35.739125676 +0200
@@ -168,6 +168,7 @@ typedef struct element {
#define CMD_STDIN_REDIR 0x400 /* async command needs implicit flags |= CMD_IGNORE_RETURN;
+
+ begin_unwind_frame ("pipe-file-descriptors");
+ lstdin = -1;
+#if 1
+ if (!asynchronous && pipe_out == NO_PIPE && prev > 0
+ && cmd->type != cm_subshell && ((cmd->flags & CMD_WANT_SUBSHELL) == 0))
+{
+ lstdin = move_to_high_fd(0, 0, 255);
+ if (lstdin > 0)
+ {
+ dup2(prev, 0);
+ close(prev);
+ prev = NO_PIPE;
+ cmd->flags |= CMD_SYNC_PIPE;
+ add_process((char*)0, getpid());
+ stop_pipeline (0, cmd);
+ add_unwind_protect (restore_stdin, lstdin);
+ }
+}
+#endif
+ if (prev >= 0)
+add_unwind_protect (close, prev);
+
exec_result = execute_command_internal (cmd, asynchronous, prev, pipe_out, fds_to_close);
+ if (lstdin > 0)
+{
+ dup2(lstdin, 0);
+ close(lstdin);
+}
+
if (prev >= 0)
close (prev);
+ discard_unwind_frame ("pipe-file-descriptors");
+
#if defined (JOB_CONTROL)
UNBLOCK_CHILD (oset);
#endif
+ if (cmd->flags & CMD_SYNC_PIPE)
+{
+ addjstatus(cmd, exec_result);
+ cmd->flags &= ~CMD_SYNC_PIPE;
+}
+
QUIT;
return (exec_result);
}
--- jobs.c
+++ jobs.c 2010-08-16 15:48:19.479125702 +0200
@@ -260,7 +260,6 @@ static int processes_in_job __P((int));
static void realloc_jobs_list __P((void));
static int compact_jobs_list __P((int));
static int discard_pipeline __P((PROCESS *));
-static void add_process __P((char *, pid_t));
static void print_pipeline __P((PROCESS *, int, int, FILE *));
static void pretty_print_job __P((int, int, FILE *));
static void set_current_job __P((int));
@@ -1065,7 +1064,7 @@ nohup_job (job_index)
if (js.j_jobslots == 0)
return;
- if (temp = jobs[job_index])
+ if ((temp = jobs[job_index]))
temp->flags |= J_NOHUP;
}
@@ -1095,7 +1094,7 @@ discard_pipeline (chain)
/* Add this process to the chain being built in the_pipeline.
NAME is the command string that will be exec'ed later.
PID is the process id of the child. */
-static void
+void
add_process (name, pid)
char *name;
pid_t pid;
@@ -3396,6 +3395,34 @@ setjstatus (j)
#endif
}
+
+void
+addjstatus(COMMAND *deferred, int status)
+{
+#if defined (ARRAY_VARS)
+ int i;
+ JOB *j;
+ for (j = jobs[(i = 0)]; j && j->deferred != deferred; j = jobs[(++i)])
+;
+ if (!j || !j->deferred)
+return;
+ j->deferred = (COMMAND*)0;
+ if (status)
+{
+ PROCESS *p, *l;
+ p = j->pipe;
+ do
+ {
+ l = p;
+ p = p->next;
+ }
+ while (p != j->pipe);
+ l->status = status << 8;
+}
+ setjstatus(i);
+#endif
+}
+
void
run_sigchld_trap (nchild)
int nchild;
--- jobs.h
+++ jobs.h 2010-08-16 15:47:22.463125472 +0200
@@ -177,6 +177,8 @@ extern void save_pipeline __P((int));
extern void restore_pipeline __P((int));
extern void start_pip