Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Using "source" in a function breaks job control

On Apr 28, 11:18am, Peter Stephenson wrote:
} Subject: Re: Using "source" in a function breaks job control
} vi() { vim -u NONE -N; print "vim exited $?" }
} and that prints the wrong status if vim was suspended --- despite the
} fact I can see the status of the vim process being updated in addbgstatus().
} Then it occurred to me that actually that's inevitable, if I've
} understood what's going on.  vim was suspended from the parent shell,
} and remains a child of that --- but we've forked at that point, and the
} print is going to happen in the forked copy.  That can never see the
} status of the exited vim unless there's some complex communication about
} process statuses with the parent shell which even the Seeress of the
} myth didn't foresee.

Ok, that makes perfect sense.  For point of contrast, given an equivalent
function, bash stops vim but the function immediately continues without
stopping; ksh 93u-1 (ubuntu) gets really confused:

$ vi() { vim -u NONE -N; echo $?; }
$ vi
[2] + Stopped                  vi
$ jobs
[2] + Stopped                  vi
[1] -  Running                 vi

Note that $? does not reflect that vim has been suspended.  Both jobs
are actually stopped even though job 1 still says "Running".

$ fg %1    
ksh: fg: no such job
$ fg

Job 2 is the function, job 1 is vim, but there's no way to bring vim
back into the foreground again except:

$ ps x | grep vim
20687 pts/0    T      0:00 vim -u NONE -N
$ kill -CONT 20687; wait
(vim resumes and I can exit from it)

(Also if I run "vim" directly from the command line and stop it and
"echo $?" I get 276 in ksh93, 148 in bash and zsh.)  

} Then it occurred to me that because it hasn't got the updated status of
} the vim, the subshell will continue for ever more to think it has status
} 148, so without the "print" it's going to exit with that status when it
} gets to the end of the function.  It's that subshell status that the
} main shell reports (reasonably enough, you'd have thought) as the
} overall status of the job.

This also makes sense.

} We could do some clever stuff with piping status information when we
} restart the subshell to update it about the exit status of the thing
} that got suspended.

I don't think that's necessary, and it I suspect it creates weird issues
when things are backgrounded instead of foregrounded.  Documentation is
probably sufficient here, it's (emperically) pretty unusual for the user
of an interactive shell to care about these exit values as long as all
the processes stop and restart in the right order.

} A simple alternative might be for the subshell to set the status of the
} process that caused it to fork to 0.  But this breaks any logic
} depending on the exit status --- at least the 148 tells you something
} funny is going on.

Perhaps there's some way to preserve that status without propagating it
as the exit of the whole subshell?

Messages sorted by: Reverse Date, Date, Thread, Author