Hi All, While trying to implement an function autoload feature, with a lazier function loading and invocation than the example provided in bash doc, I bumped into this bash bug (or feature, you let me know).
I asked stackoverflow for some ideas, one pointed me to command_not_found_handle() that I was not aware off and looked promising for what I wanted to achieve. This SO post is quite big, so I will report here a shorter version. In a nutshell to implement a function autoloading I want to plug into command_not_found_handle(), but I need command_not_found_handle()be evaluated in the shell context, not in a subshell. At the moment BASH_VERSION='5.0.16(14)-release' (and all way back) the is wrongly called as a sub-shell, that doesn't hurt the command-not-found packages found in many distro as at this point they don't care about setting things in the shell instance, so their implementation is good enough. To demonstrate the bug, suffice to do this function command_not_found_handle { echo $$ ; sh -c 'echo $PPID' } When run in shell context we got the correct answer $ function command_not_found_handle > { echo $$ ; sh -c 'echo $PPID' > } $ $ command_not_found_handle 11370 11370 But when called from 'not found' context we got $ ddd # dd not found on my system then call command_not_found_handle 11779 11783 $ As we see here, $$ lies pretend to be the shell PID 11779 while it real $$ is 11783, so a child. This is a real problem because then there is nothing I can do in command_not_found_handle) to setup things in the shell context, i.e not new alias setup, no new functin define, etc... I propose a fix, yet bear in mind hacking bash is not my day to day job :) so it must be reviewed by gurus. I send the proposed [atch separatly. With this fix I got this run PW$ PS1='$ ' $ function command_not_found_handle > { echo $$ ; sh -c 'echo $PPID' > } $ ddd 12165 12165 $ function command_not_found_handle > { echo in cnf > A="cnf-was-called" > return 127 > } $ A='' $ ddd in cnf $ echo $A cnf-was-called $ Meaning now command_not_found_handle() is a real function called from the shel context, shell context can then be touch (vars, alias, functions, etc..) what I need to implement my autoload mechanism. Not that it is indeed possible to chain the handlers, so assuming a command-not-found package installed I got this on ubuntu. $ declare -f command_not_found_handle command_not_found_handle () { if [ -x /usr/lib/command-not-found ]; then /usr/lib/command-not-found -- "$1"; return $?; else if [ -x /usr/share/command-not-found/command-not-found ]; then /usr/share/command-not-found/command-not-found -- "$1"; return $?; else printf "%s: command not found\n" "$1" 1>&2; return 127; fi; fi } And a run gives $ ddd Command 'ddd' not found, but can be installed with: sudo apt install ddd If I now want to install my handler I rename the current handler # Rename current command_not_found_handle _cnf_body=$(declare -f command_not_found_handle | tail -n +2) eval "function _cnf_prev $_cnf_body" Then I create mine chaining to the prev one function command_not_found_handle { echo in cnf A="cnf-was-called" _cnf_prev "$@" } $ unset A $ ddd in cnf Command 'ddd' not found, but can be installed with: sudo apt install ddd $ echo $A cnf-was-called This shows that my handler was called, on failure to find a function, it forward to the previous handler, then it shows that it ran in the shell contect as A= is set correfctly. I got no memory leak detected with this patch, but again review thouroughly. Hope this helps. Cheers, Phi