Eu posso explicar, mas não sei como consertar isso. Está me incomodando há anos também. Pelo menos 20. Não é um único bug em qualquer programa em particular, mas uma condição de corrida entre 3 programas que estão se comportando individualmente como planejados, e é geral o suficiente para se aplicar a muitas combinações de programas.
Quando você digita ^Z
durante a leitura de uma página man, envia um SIGTSTP
para o grupo de processos em primeiro plano, que consiste no man
process e seus descendentes. O pager ( less
) é um desses descendentes.
man
é suspenso imediatamente, mas less
não é. Tem um manipulador de sinal. E há uma boa razão para isso. Ele mudou o modo tty (para poder ler os caracteres assim que eles são digitados), e quer restaurar o modo original e arrumar a tela antes de abrir mão do controle. Então isso acontece.
Enquanto isso (essa é uma palavra animada), o shell notou que o processo man
está parado. E aqui está a parte ruim: o shell não tem idéia de que o processo less
existe. Os processos Unix geralmente não têm como saber sobre seus netos. Então, do ponto de vista do shell, o trabalho parou, mesmo que na realidade less
ainda não tenha terminado de arrumar.
Atuando em informações incompletas, o shell se coloca de volta em primeiro plano, imprime uma mensagem de notificação de trabalho, configura o modo tty para seu próprio editor de linhas e imprime um prompt. Mas está correndo com less
, que ainda está tentando arrumar. Enquanto o shell está imprimindo um prompt e definindo o modo atty, menos está ocupado movendo o cursor e limpando a linha inferior da tela (onde estava o prompt less
).
Por ser uma corrida, há muitos resultados possíveis, dependendo da ordem das operações, mas a mais irritante é a seguinte:
- o shell imprime a notificação de trabalho, define o modo tty para seu editor de linhas e imprime um prompt.
-
less
move o cursor para o canto inferior esquerdo, limpa a linha inferior (apagando o promptless
e o prompt do shell) e restaura o modo tty padrão genérico (modo "cozido"). - o shell se coloca em primeiro plano e começa a aceitar entrada.
Agora você está olhando para uma linha em branco precedida por uma notificação de trabalho, com o shell tentando ler pressionamentos de tecla, não sabendo que o tty foi configurado para o modo cozido e, portanto, não enviará nenhuma entrada para o shell até que uma linha completa seja digitada.
Você pode realmente digitar um comando aqui, e até mesmo editá-lo, se for inteligente o bastante para descobrir como fazer com que sua entrada seja passada pelo editor de linha do tty e pelo editor de linha do shell, com feedback imediato vindo apenas do editor de linha do tty.
É uma situação complicada, e consertar parece exigir mais coordenação entre os processos do que o kernel atualmente permite. O shell precisa de uma maneira de consultar o estado de suspensão do grupo de processos como um todo e uma maneira de distinguir entre processos netos como less
que manipulam SIGTSTP
com a intenção de suspender-se logo depois, e netos tipo daemon que são apenas ignorando SIGTSTP
com a intenção de continuar executando em segundo plano enquanto o restante do trabalho é suspenso.