Hello Guus, hello Ziga I found the problem.
Guus Sliepen schrieb am Tue 27. Mar, 12:46 (+0200): > On Thu, Mar 22, 2007 at 05:23:36PM +0100, Jörg Sommer wrote: > > > > The patch didn't work. I then reinstalled the original script, but > > > removed all redirections to /dev/null. It still complains about not > > > being able to open /dev/null. > > > > Oh, can you add a set -x before the PATH assignment and than look, if you > > can see between which lines the message is printed. BTW: You can stop the > > output with ctrl+s. > > I see the following: > > [...] > + [ ! -f /proc/stat ] > + sleep 0.2 > /sbin/bootchartd: 1: Can't open /dev/null > /sbin/bootchartd: 1: Can't open /dev/null > /sbin/bootchartd: 1: + [ -n yes ] > /sbin/bootchartd: 1: Can't open /dev/null > Can't open /dev/null The lines above belong to these lines: while [ ! -f /proc/stat ]; do sleep $SAMPLE_PERIOD; done sleep $SAMPLE_PERIOD # Run loggers in background log_output "cat /proc/stat" proc_stat.log & # /proc/diskstats is available in 2.6 kernels [ -f /proc/diskstats ] && log_output "cat /proc/diskstats" proc_diskstats.log & log_output "cat /proc/*/stat" proc_ps.log & This is a short form of the problamatical code: #!/bin/dash foo() { echo $! /bin/ls -l /proc/$$/fd /bin/sleep 2 } foo & foo If you use strace, you can find these lines: [pid 17961] clone(Process 17964 attached child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x3001fd68) = 17964 [pid 17961] wait4(-1, Process 17961 suspended <unfinished ...> [pid 17963] close(10) = 0 [pid 17963] rt_sigaction(SIGINT, {SIG_IGN}, {0x100115b0, ~[KILL STOP RTMIN RT_1], 0}, 8) = 0 [pid 17963] rt_sigaction(SIGQUIT, {SIG_IGN}, {SIG_DFL}, 8) = 0 [pid 17963] close(0) = 0 [pid 17963] open("/dev/null", O_RDONLY) = 0 [pid 17963] write(1, "\n", 1 ) = 1 And there you see, dash tries to open /dev/null. The corresponding code is the following: (dash-0.5.3/src/jobs.c) /* * Fork off a subshell. If we are doing job control, give the subshell its * own process group. Jp is a job structure that the job is to be added to. * N is the command that will be evaluated by the child. Both jp and n may * be NULL. The mode parameter can be one of the following: * FORK_FG - Fork off a foreground process. * FORK_BG - Fork off a background process. * FORK_NOJOB - Like FORK_FG, but don't give the process its own * process group even if job control is on. * * When job control is turned off, background processes have their standard * input redirected to /dev/null (except for the second and later processes * in a pipeline). * * Called with interrupts off. */ STATIC inline void forkchild(struct job *jp, union node *n, int mode) { int oldlvl; TRACE(("Child shell %d\n", getpid())); oldlvl = shlvl; shlvl++; closescript(); clear_traps(); #if JOBS /* do job control only in root shell */ jobctl = 0; if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) { pid_t pgrp; if (jp->nprocs == 0) pgrp = getpid(); else pgrp = jp->ps[0].pid; /* This can fail because we are doing it in the parent also */ (void)setpgid(0, pgrp); if (mode == FORK_FG) xtcsetpgrp(ttyfd, pgrp); setsignal(SIGTSTP); setsignal(SIGTTOU); } else #endif if (mode == FORK_BG) { ignoresig(SIGINT); ignoresig(SIGQUIT); if (jp->nprocs == 0) { close(0); if (open(_PATH_DEVNULL, O_RDONLY) != 0) sh_error("Can't open %s", _PATH_DEVNULL); } } Three lines above you can see the problamatical line of code. The path is hard coded and there's (no) escape. The only way I found out is job control. #!/bin/dash exec 3>&1 <>/dev/null >&0 set -m foo() { echo $! /bin/ls -l /proc/$$/fd /bin/sleep 2 } echo hello >&3 foo & foo echo bye >&3 For job control bootchart needs a heavy rewrite, but I also think it can gain something. The other way is to try to redirect the shell error to /dev/null. What do you think Ziga? Bye, Jörg. -- “Perl—the only language that looks the same before and after RSA encryption.” (Keith Bostic)
pgpzB7eE2nZ3Y.pgp
Description: PGP signature