0
#!/usr/bin/env bash
sleep 3 &                               # Spawn a child

trap '
    pgrep -P $$                         # Outputs one PID as expected
    PIDS=( $( pgrep -P $$ ) )           # Saves an extra nonexistant PID
    echo "PIDS: ${PIDS[@]}"             # You can see it is the last one
    ps -o pid= "${PIDS[@]:(-1)}" ||
    echo "Dafuq is ${PIDS[@]:(-1)}?"    # Yep, it does not exist!

' 0 1 2 3 15

It outputs

11800
PIDS: 11800 11802
Dafuq is 11802?

It only happens with traps. Why is a nonexistent PID appended to the array? And how to avoid this odd behaviour?

Jolta
  • 2,620
  • 1
  • 29
  • 42
Dude
  • 11
  • 4

1 Answers1

2

By using $(...), you've created a subprocess which will execute that code.

Naturally, the parent of that process will be the current shell, so it's going to be listed.

As for the workaround, you could remove that PID from the list. First you have to know how to access the subshell PID: $$ in a script vs $$ in a subshell . Now you can filter it out (nope, it doesn't work):

PIDS=( $( pgrep -P $$ | grep -v ^$BASHPID$ ) )
Community
  • 1
  • 1
Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
  • The thing is, the odd behaviour disappears if the trap is not present. – Dude Apr 26 '15 at 19:21
  • It probably has to do with the way `trap` is implemented in bash.. but I'm not in the mood to dig into the source code, that's for sure.. :D – Karoly Horvath Apr 26 '15 at 19:26
  • I guess so, but how to avoid is still bugging me. – Dude Apr 26 '15 at 19:29
  • this is a kinda similar problem, that often arises: http://serverfault.com/questions/367921/how-to-prevent-ps-reporting-its-own-process haven't you tested what I've suggested? – Karoly Horvath Apr 26 '15 at 19:32
  • Thanks Karoly, the first one was useful. So yeah `$( pgrep -P $$ )` spawns the odd process. EDIT: Sorry I mistyped, but anyway I still was wrong. So a workaround would be to manually remove that subshell process id, is there a better way? – Dude Apr 26 '15 at 20:00
  • Oh, `$BASHPID` changes after the pipe, so `grep -v` won't filter it `echo $BASHPID $( echo $BASHPID; echo $BASHPID; true | echo $BASHPID )` outputs `11623 13404 13404 13406` – Dude Apr 26 '15 at 20:42
  • heck, you're right... dunno, do the query twice, keep only the ids that appear in both :) But you *really should* use `$!` and avoid pgrep... – Karoly Horvath Apr 26 '15 at 21:08