Orphaned zsh processes from interactive shells executing commands
I noticed that when using powerlevel10k, commands run by tools forcing an interactive shell leave orphaned zsh processes owned by launchd. In this case they're doing this to get the interactive environment for the user, I believe IntelliJ and VSCode do something similar:
501 53600 1 0 10:40am ?? 0:00.00 /bin/zsh -l -i -c "/Users/dannyt/Applications/Fleet 1.33.90 Public Preview.app/Contents/app/bin/printenv" "env"
501 53807 1 0 10:40am ?? 0:00.00 /bin/zsh -l -i -c "/Users/dannyt/Applications/Fleet 1.33.90 Public Preview.app/Contents/app/code-cache/2340e3746bf772caab876db94f891b529a20a0edde0829ae521b36f56b2383ca/fsdaemon-1.33.90" "env"
501 54318 1 0 10:40am ?? 0:00.00 /bin/zsh -l -i -c /Users/dannyt/Applications/Fleet 1.33.90 Public Preview.app/Contents/app/bin/printenv env
501 54693 1 0 10:40am ?? 0:00.00 /bin/zsh -l -i -c /Users/dannyt/Applications/Fleet\ 1.33.90\ Public\ Preview.app/Contents/app/bin/printenv env
501 55077 1 0 10:40am ?? 0:00.00 /bin/zsh -l -i -c /Users/dannyt/Applications/Fleet\ 1.33.90\ Public\ Preview.app/Contents/app/bin/printenv
501 55453 1 0 10:40am ?? 0:00.00 /bin/zsh -l -i -c /Users/dannyt/Applications/Fleet\ 1.33.90\ Public\ Preview.app/Contents/app/bin/printenv env
501 56414 1 0 10:41am ?? 0:00.00 /bin/zsh -l -i -c /Users/dannyt/Applications/Fleet 1.33.90 Public Preview.app/Contents/app/bin/printenv
501 56827 1 0 10:41am ?? 0:00.00 /bin/zsh -l -i -c /Users/dannyt/Applications/Fleet\ 1.33.90\ Public\ Preview.app/Contents/app/bin/printenv
501 57585 1 0 10:42am ?? 0:00.00 /bin/zsh -l -i -c /Users/dannyt/Applications/Fleet\ 1.33.90\ Public\ Preview.app/Contents/app/bin/printenv env
501 80361 1 0 11:51am ?? 0:00.00 /bin/zsh -l -i -c "/Users/dannyt/Applications/Fleet 1.33.90 Public Preview.app/Contents/app/code-cache/2340e3746bf772caab876db94f891b529a20a0edde0829ae521b36f56b2383ca/fsdaemon-1.33.90" "env"
I can reproduce if I run commands interactively:
❯ zsh -ic 'echo hi'
hi
❯ ps -ef | grep echo
501 82079 1 0 11:54am ttys001 0:00.00 zsh -ic echo hi
501 82081 1 0 11:54am ttys001 0:00.00 zsh -ic echo hi
One of the processes exits soon after, but the other stays running indefinitely:
501 82079 1 0 11:54am ttys001 0:00.00 zsh -ic echo hi
I bisected my .zshrc and confirmed that disabling powerlevel10k avoids the problem. That's as much as I've been able to discover I'm afraid, it's not obvious to me which of the spawned shells this is:
Analysis of sampling zsh (pid 82079) every 1 millisecond
Process: zsh [82079]
Path: /bin/zsh
Load Address: 0x1003f0000
Identifier: zsh
Version: 100
Code Type: ARM64E
Platform: macOS
Parent Process: ??? [1]
Date/Time: 2024-04-13 11:55:18.864 +1000
Launch Time: 2024-04-13 11:54:03.648 +1000
OS Version: macOS 14.4.1 (23E224)
Report Version: 7
Analysis Tool: /usr/bin/sample
Physical footprint: 1649K
Physical footprint (peak): 1729K
Idle exit: untracked
----
Call graph:
2566 Thread_10185983 DispatchQueue_1: com.apple.main-thread (serial)
2566 start (in dyld) + 2360 [0x1909360e0]
2566 zsh_main (in zsh) + 916 [0x10042331c]
2566 run_init_scripts (in zsh) + 616 [0x100422108]
2566 source (in zsh) + 764 [0x1004224b0]
2566 loop (in zsh) + 804 [0x100420450]
2566 execode (in zsh) + 204 [0x1004055b4]
2566 execlist (in zsh) + 1936 [0x100405d70]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1d98c [0x10040d98c]
2566 execif (in zsh) + 304 [0x10042efb4]
2566 execlist (in zsh) + 1936 [0x100405d70]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1e0d4 [0x10040e0d4]
2566 execbuiltin (in zsh) + 1604 [0x1003f360c]
2566 bin_dot (in zsh) + 348 [0x1003fff2c]
2566 source (in zsh) + 764 [0x1004224b0]
2566 loop (in zsh) + 804 [0x100420450]
2566 execode (in zsh) + 204 [0x1004055b4]
2566 execlist (in zsh) + 1936 [0x100405d70]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1d98c [0x10040d98c]
2566 execif (in zsh) + 304 [0x10042efb4]
2566 execlist (in zsh) + 1936 [0x100405d70]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1d98c [0x10040d98c]
2566 execif (in zsh) + 304 [0x10042efb4]
2566 execlist (in zsh) + 1936 [0x100405d70]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1e0d4 [0x10040e0d4]
2566 execbuiltin (in zsh) + 1604 [0x1003f360c]
2566 bin_dot (in zsh) + 348 [0x1003fff2c]
2566 source (in zsh) + 764 [0x1004224b0]
2566 loop (in zsh) + 804 [0x100420450]
2566 execode (in zsh) + 204 [0x1004055b4]
2566 execlist (in zsh) + 668 [0x10040587c]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16124 [0x100406124]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1ab0c [0x10040ab0c]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1ad44 [0x10040ad44]
2566 doshfunc (in zsh) + 1260 [0x10040981c]
2566 runshfunc (in zsh) + 224 [0x100409d28]
2566 execode (in zsh) + 204 [0x1004055b4]
2566 execlist (in zsh) + 1936 [0x100405d70]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1d98c [0x10040d98c]
2566 execif (in zsh) + 304 [0x10042efb4]
2566 execlist (in zsh) + 1936 [0x100405d70]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1dcd4 [0x10040dcd4]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1ad44 [0x10040ad44]
2566 doshfunc (in zsh) + 1260 [0x10040981c]
2566 runshfunc (in zsh) + 224 [0x100409d28]
2566 execode (in zsh) + 204 [0x1004055b4]
2566 execlist (in zsh) + 1936 [0x100405d70]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1dcd4 [0x10040dcd4]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1ad44 [0x10040ad44]
2566 doshfunc (in zsh) + 1260 [0x10040981c]
2566 runshfunc (in zsh) + 224 [0x100409d28]
2566 execode (in zsh) + 204 [0x1004055b4]
2566 execlist (in zsh) + 1936 [0x100405d70]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1d98c [0x10040d98c]
2566 exectry (in zsh) + 124 [0x10042f55c]
2566 execlist (in zsh) + 668 [0x10040587c]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16124 [0x100406124]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1ab0c [0x10040ab0c]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1ad44 [0x10040ad44]
2566 doshfunc (in zsh) + 1260 [0x10040981c]
2566 runshfunc (in zsh) + 224 [0x100409d28]
2566 execode (in zsh) + 204 [0x1004055b4]
2566 execlist (in zsh) + 1936 [0x100405d70]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1d98c [0x10040d98c]
2566 execif (in zsh) + 304 [0x10042efb4]
2566 execlist (in zsh) + 1936 [0x100405d70]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1d98c [0x10040d98c]
2566 execif (in zsh) + 304 [0x10042efb4]
2566 execlist (in zsh) + 852 [0x100405934]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1bf00 [0x10040bf00]
2566 prefork (in zsh) + 476 [0x100456800]
2566 ??? (in zsh) load address 0x1003f0000 + 0x66e20 [0x100456e20]
2566 getproc (in zsh) + 464 [0x100408958]
2566 execode (in zsh) + 204 [0x1004055b4]
2566 execlist (in zsh) + 1936 [0x100405d70]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1dcd4 [0x10040dcd4]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1ad44 [0x10040ad44]
2566 doshfunc (in zsh) + 1260 [0x10040981c]
2566 runshfunc (in zsh) + 224 [0x100409d28]
2566 execode (in zsh) + 204 [0x1004055b4]
2566 execlist (in zsh) + 1936 [0x100405d70]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1d98c [0x10040d98c]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1aec8 [0x10040aec8]
2566 execlist (in zsh) + 1936 [0x100405d70]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1d98c [0x10040d98c]
2566 exectry (in zsh) + 124 [0x10042f55c]
2566 execlist (in zsh) + 852 [0x100405934]
2566 ??? (in zsh) load address 0x1003f0000 + 0x16410 [0x100406410]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1b3fc [0x10040b3fc]
2566 ??? (in zsh) load address 0x1003f0000 + 0x1d27c [0x10040d27c]
2566 open (in libsystem_kernel.dylib) + 64 [0x190c89de8]
2566 __open (in libsystem_kernel.dylib) + 8 [0x190c7ec50]
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
zsh 82079 dannyt cwd DIR 1,15 640 2 /
zsh 82079 dannyt txt REG 1,15 1361200 1152921500312524143 /bin/zsh
zsh 82079 dannyt txt REG 1,15 170992 1152921500312526618 /usr/lib/zsh/5.9/zsh/zutil.so
zsh 82079 dannyt txt REG 1,15 118864 1152921500312526602 /usr/lib/zsh/5.9/zsh/terminfo.so
zsh 82079 dannyt txt REG 1,15 338576 1152921500312526554 /usr/lib/zsh/5.9/zsh/complete.so
zsh 82079 dannyt txt REG 1,15 136880 1152921500312526598 /usr/lib/zsh/5.9/zsh/system.so
zsh 82079 dannyt txt REG 1,15 171328 1152921500312526588 /usr/lib/zsh/5.9/zsh/parameter.so
zsh 82079 dannyt txt REG 1,15 211120 1152921500312526552 /usr/lib/zsh/5.9/zsh/compctl.so
zsh 82079 dannyt txt REG 1,15 117920 1152921500312526570 /usr/lib/zsh/5.9/zsh/langinfo.so
zsh 82079 dannyt txt REG 1,15 593088 1152921500312526608 /usr/lib/zsh/5.9/zsh/zle.so
zsh 82079 dannyt txt REG 1,15 208144 1152921500312526556 /usr/lib/zsh/5.9/zsh/complist.so
zsh 82079 dannyt txt REG 1,15 118688 1152921500312526590 /usr/lib/zsh/5.9/zsh/regex.so
zsh 82079 dannyt txt REG 1,15 135696 1152921500312526562 /usr/lib/zsh/5.9/zsh/datetime.so
zsh 82079 dannyt txt REG 1,15 136512 1152921500312526568 /usr/lib/zsh/5.9/zsh/files.so
zsh 82079 dannyt 1w CHR 3,2 0t0 333 /dev/null
zsh 82079 dannyt 2w CHR 3,2 0t0 333 /dev/null
zsh 82079 dannyt 11 PIPE 0xa7a75ca958b35c84 16384
Can you reproduce this with the following command?
() {
emulate -L zsh -o err_return -o xtrace
if [[ -e ~/powerlevel10k ]]; then
command git -C ~/powerlevel10k pull
else
command git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/powerlevel10k
fi
command rm -rf ~/z
command mkdir -p ~/z
command cat >~/z/.zshrc <<\END
source ~/z/.p10k.zsh
source ~/powerlevel10k/powerlevel10k.zsh-theme
END
command cat >~/z/.p10k.zsh <<\END
POWERLEVEL9K_MODE=ascii
POWERLEVEL9K_DISABLE_HOT_RELOAD=true
END
repeat 10 ZDOTDIR=~/z command zsh --no-globalrcs -ic 'echo hi'
command sleep 1
command ps -ef | command grep -E 'echo hi$'
}
Yes, rarely. When I do this manually from my regular shell I can reproduce almost every time. It might be a complete coincidence, but it seems to help if I start from scratch (i.e. remove z and powerlevel10k directories) before running the function:
+(anon):3> [[ -e /Users/dannyt/powerlevel10k ]]
+(anon):6> git clone '--depth=1' https://github.com/romkatv/powerlevel10k.git /Users/dannyt/powerlevel10k
Cloning into '/Users/dannyt/powerlevel10k'...
remote: Enumerating objects: 92, done.
remote: Counting objects: 100% (92/92), done.
remote: Compressing objects: 100% (75/75), done.
remote: Total 92 (delta 18), reused 77 (delta 13), pack-reused 0
Receiving objects: 100% (92/92), 349.37 KiB | 5.54 MiB/s, done.
Resolving deltas: 100% (18/18), done.
+(anon):9> rm -rf /Users/dannyt/z
+(anon):10> mkdir -p /Users/dannyt/z
+(anon):12> cat
+(anon):17> cat
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):23> sleep 1
+(anon):24> ps -ef
+(anon):24> grep -E 'echo hi$'
501 21276 1 0 9:47am ttys001 0:00.00 zsh --no_globalrcs -ic echo hi
501 21277 1 0 9:47am ttys001 0:00.00 zsh --no_globalrcs -ic echo hi
❯ ps -ef | grep -E 'echo hi$'
501 21276 1 0 9:47am ttys001 0:00.00 zsh --no_globalrcs -ic echo hi
Can you reproduce this if you replace sleep 1 with sleep 10?
Yeah:
+(anon):3> [[ -e /Users/dannyt/powerlevel10k ]]
+(anon):6> git clone '--depth=1' https://github.com/romkatv/powerlevel10k.git /Users/dannyt/powerlevel10k
Cloning into '/Users/dannyt/powerlevel10k'...
remote: Enumerating objects: 92, done.
remote: Counting objects: 100% (92/92), done.
remote: Compressing objects: 100% (75/75), done.
remote: Total 92 (delta 18), reused 77 (delta 13), pack-reused 0
Receiving objects: 100% (92/92), 349.37 KiB | 5.06 MiB/s, done.
Resolving deltas: 100% (18/18), done.
+(anon):9> rm -rf /Users/dannyt/z
+(anon):10> mkdir -p /Users/dannyt/z
+(anon):12> cat
+(anon):17> cat
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):22> ZDOTDIR=/Users/dannyt/z zsh --no-globalrcs -ic 'echo hi'
hi
+(anon):23> sleep 10
+(anon):24> ps -ef
+(anon):24> grep -E 'echo hi$'
501 70025 1 0 7:25pm ttys004 0:00.00 zsh --no_globalrcs -ic echo hi
They don't linger forever, do they?
Yes, when they hang up like this, it seems they do:
❯ ps -ef | grep -E 'echo hi$'
501 70025 1 0 7:25pm ttys004 0:00.00 zsh --no_globalrcs -ic echo hi
❯ date
Mon 15 Apr 2024 19:38:13 AEST
Interesting. I cannot reproduce this. I'll dig into this.
Thanks, let me know if there's anything else I can do to eliminate problems here. It's a real head scratcher.
What is the output of this command?
typeset -pm 'P9K_SSH|_P9K_SSH_TTY|TTY'
true &; ZDOTDIR=~/z zsh --no-globalrcs -ic 'echo hi'; true&
I am assuming you have ~/powerlevel10k and ~/z left over from the previous command.
❯ typeset -pm 'P9K_SSH|_P9K_SSH_TTY|TTY'
true &; ZDOTDIR=~/z zsh --no-globalrcs -ic 'echo hi'; true&
typeset TTY=/dev/ttys004
export _P9K_SSH_TTY=/dev/ttys004
export -i P9K_SSH=0
[1] 18891
[1] + 18891 done true
hi
[1] 18897
[1] + 18897 done true