Bash traps não executando no último cmd para scripts passados com -c

2

Veja um exemplo:

$ (newline=$'\n'; bash -c "trap 'trap ERR; echo handler' ERR; set -e;${newline}/bin/false")

O manipulador será executado se eu fizer o seguinte:

  • remova a nova linha
  • armadilha em EXIT em vez
  • adicione outro comando no final

Eu suspeito que o bash tem uma otimização para apenas chamar exec se houver apenas um comando, e a nova linha seguida por um único comando está acionando-o.

Eu tenho provas circunstanciais: corri sob a pressão; os cmds anteriores serão executados, mas o último apenas chama execv.

Eu corri para isso com o GNU make usando .ONESHELL e uma armadilha para imprimir o código de saída e o nome do arquivo, mas se a última coisa falhar, a armadilha não será executada.

Obrigado antecipadamente.

    
por Brian Vandenberg 21.04.2016 / 01:34

1 resposta

1

Esqueci-me desta questão. Eu contribuí com uma correção para atacar em 2016 :

                   4/22
                   ----
builtins/evalstring.c
    - should_suppress_fork: don't suppress the fork if there are any traps
      set, since that requires that we hang around to react to a signal or
      collect the command's exit status and run something.  Fixes bug
      reported by Brian Vandenberg

Como especulei na minha pergunta, bash realmente tem otimizações no lugar. Já faz algum tempo desde que eu olhei para o código, mas mais ou menos faz o seguinte:

  1. Analise até que uma expressão completa seja identificada, avalie-a e interprete ou execute o que resta após a avaliação
  2. Repetir (1) até restar apenas uma expressão
  3. Se a última expressão não precisar de assistência do shell e puder ser passada para uma função exec() family, faça isso

Minha correção foi adicionar à definição de "não requer assistência do shell", fazendo com que verifique se há armadilhas em vigor.

    
por 31.07.2018 / 20:14

Tags