#604993 dash as /bin/sh causes $PPID to be wrong in child when invoked via system() call

Package:
dash
Source:
dash
Description:
POSIX-compliant shell
Submitter:
Tim Connors
Date:
2011-11-27 01:48:20 UTC
Severity:
wishlist
Tags:
Blocked By:
Bug Title
642835

  0

sexplib310: FTBFS: E: Command /usr/bin/ocamlbuild terminated with error code 10

important stable testing unstable over 9 years ago

642706

  12

ocamlbuild: questionable job control

important stable testing unstable about 5 years ago

#604993#5
Date:
2010-11-26 03:05:54 UTC
From:
To:
Any calls to system() invokes

sh -c <prog> <args>

When /bin/sh is linked to dash, if <prog> is a shell script (/bin/sh
or /bin/bash), that shell script sees $PPID as being the "sh -c" process.

If /bin/sh is linked to bash, <prog> sees $PPID as being the actual
parent, which is a hell of a lot more useful (and in my case, required
for functionality of scripts I wrote a long time ago and I believe are
acting correctly).

My suspicion is that dash is doing an extra fork before exec, which
seems entirely useless, and not exactly in keeping with the
"lightweight and fast" aims of dash (forks can be expensive - glad
I don't have dash installed on our slowaris boxes!).

I think I can confirm this with this simple example:

75318,3> perl -e 'system("/bin/bash -c \"sleep 60\"");'
    75319,7> ps axuf | grep -A5 perl.*[s]ystem
    twc      19561  0.0  0.0  20132  1676 pts/118  S+   13:49   0:00                      \_ perl -e system("/bin/bash -c \"sleep 60\"");
twc      19562  0.0  0.0   9512   616 pts/118  S+   13:49   0:00                          \_ sleep 60


75320,5> perl -e 'system("/bin/dash -c \"sleep 60\"");'
    75320,8> ps axuf | grep -A5 perl.*[s]ystem
    twc      19752  0.0  0.0  20132  1676 pts/118  S+   13:49   0:00                      \_ perl -e system("/bin/dash -c \"sleep 60\"");
    twc      19753  0.0  0.0   8104   632 pts/118  S+   13:49   0:00                          \_ /bin/dash -c sleep 60
    twc      19754  0.0  0.0   9512   616 pts/118  S+   13:49   0:00                              \_ sleep 60



I have marked this as "grave", because it breaks unrelated parts of
the system: Sure, it's a shell script using /bin/sh (linked to dash)
that broke in this case, but anyone is free to use $PPID (via
/proc/.../status), and all it took was for the job of "sh -c" (that
system() always uses) having been taken over by the dash package
instead of bash.  Never mind the fact that I didn't actively install
dash - it came in with dependencies and eventually decided to ignore
my choice for /bin/sh to be manually linked to bash after several
upgrades where it obeyed me).

#604993#10
Date:
2010-11-26 04:04:38 UTC
From:
To:
severity 604993 normal
quit

Hi Tim,

Tim Connors wrote:

Could you give an example?  I tried:

	$ sh -c 'echo $PPID; echo $$'
	18562
	18564
	$ python -c 'import os; os.system("echo $PPID; echo $$");'
	18577
	18578

so I suspect I am missing something.

No.

Please feel free to file a bug if you have ideas for improving this.
At the very least, I imagine the release notes (package release-notes)
could use some improvement.

Thanks for reporting.

Happy thanksgiving,
Jonathan

#604993#17
Date:
2010-11-26 04:53:40 UTC
From:
To:
75427,45> ps $$
  PID TTY      STAT   TIME COMMAND
 2520 pts/29   Ss     0:01 bash
75428,46> /bin/bash -c "bash -c \"echo \\\$PPID ; ps \\\$PPID\""
2520
  PID TTY      STAT   TIME COMMAND
 2520 pts/29   Ss     0:01 bash
75429,47> /bin/dash -c "bash -c \"echo \\\$PPID ; ps \\\$PPID\""
5542
  PID TTY      STAT   TIME COMMAND
 5542 pts/29   S+     0:00 /bin/dash -c bash -c "echo \$PPID ; ps \$PPID"

(the first /bin/bash or /bin/dash mimics /bin/sh being called with those
set as links, the second /bin/bash mimicks the #!/bin/bash line of a
script being called by system() (equivalentl results with #!/bin/sh or
#!/bin/dash), or indeed any process that reads the PPid line from
/proc/.../status.

I strongly disagree.

It causes the PPid line in /proc/$pid/status to be WRONG for any program
or script if it was executed by the system() routine provided in libc, if
and only if dash is installed as /bin/sh.

#604993#22
Date:
2010-11-26 05:24:37 UTC
From:
To:
forcemerge 436466 604993
tags 436466 + upstream
quit

Tim Connors wrote:
command given to -c to exec it).

It falls cleanly into the "patches welcome" category[1].

Survey of existing behavior:

	$ for shell in dash ksh93 bash mksh pdksh
	> do
	>	$shell -c 'printf "%s " $$; bash -c "echo \$\$"'
	> done
	18832 18833
	18834 18834
	18835 18836
	18837 18838
	18839 18841
	$ for shell in dash ksh93 bash mksh pdksh
	> do
	>	$shell -c 'bash -c "readlink /proc/\$PPID/exe"'
	> done
	/bin/dash
	/bin/bash
	/bin/bash
	/bin/mksh
	/bin/pdksh

POSIX and tradition do not require the bash/ksh behavior.  (See
http://austingroupbugs.net/ if you would like to change that.)

Have you tried "dpkg-reconfigure -plow dash"?  That should allow your
apps to continue working...

Regards,
Jonathan

[1] If you'd like to work on this, that would be excellent.  Please
feel free to email dash@vger.kernel.org with any work in progress.  No
subscription required, since the convention is to always cc all
participants.