Como atualizar a biblioteca compartilhada sem travar?

14

Aqui diz que você pode reescrever um arquivo executável e o processo será executado muito bem - ele será relido quando um processo for reiniciado.

No entanto, quando eu tento substituir um arquivo binário enquanto o processo está em execução (com scp, do dev para o servidor de teste) ele diz 'arquivo ocupado'. E se eu substituir um arquivo de biblioteca compartilhada (* .so), todos os processos que o vinculam falharão.

Por que isso? Estou esquecendo de algo? Como posso substituir os arquivos binários sem interromper / travar um processo?

    
por Sam 30.04.2013 / 11:23

2 respostas

17

Como mencionado em Por que um pacote de software roda muito bem mesmo quando está sendo atualizado? , o bloqueio é colocado no inode e não no nome do arquivo. Quando você carrega e executa um binário, o arquivo é marcado como ocupado - e é por isso que você obtém o erro ETXTBSY (arquivo ocupado) quando tenta gravar nele.

Agora, para bibliotecas compartilhadas, é um pouco diferente: as bibliotecas obtêm a memória mapeada no espaço de endereço do processo com mmap() . Embora MAP_DENYWRITE possa ser especificado, pelo menos a Glibc no Linux a ignora silenciosamente (de acordo com a página man, sinta-se à vontade para verificar as fontes) - marque esta thread . Portanto, você tem permissão para gravar o arquivo e, como é mapeado na memória, todas as alterações são visíveis quase que imediatamente - o que significa que, se você se esforçar o suficiente, poderá conseguir brick sua máquina sobrescrevendo a biblioteca.

A maneira correta de atualizar, portanto, é:

  1. removendo o arquivo, o que remove a referência aos dados do sistema de arquivos, para que ele não seja acessível para aplicativos recém-gerados que possam usá-lo, mantendo os dados acessíveis para qualquer pessoa que já tenha é aberto (ou mapeado);

  2. criando um novo arquivo com conteúdo atualizado.

Processos recém-criados usarão o conteúdo atualizado, os aplicativos em execução acessarão a versão antiga. Isso é o que qualquer utilitário de gerenciamento de pacote sensato faz. Note que não é completamente sem nenhum perigo - por exemplo, aplicativos dinamicamente carregando código (usando dlsym() e amigos) terão problemas se a API da biblioteca mudar silenciosamente.

Se você quiser estar realmente seguro, seguro, desligue o sistema, monte o sistema de arquivos a partir de outra instância do sistema operacional, atualize e atualize o sistema atualizado novamente.

    
por 30.04.2013 / 12:57
6

Uma atualização de rpm faz o mesmo - com binários e bibliotecas em execução, enquanto nada falha.

Então, qual é a diferença:

  1. desvincular arquivo
  2. escrever novo arquivo com o mesmo nome

Isto NÃO substituirá o arquivo no local: O inode referente ao binário em uso ainda está "ocupado" até que o último objeto que o mantém aberto termine. O novo arquivo será criado com um novo número de inode.

Agora, scp ou cp tentará substituir o arquivo no local - o que mudaria o conteúdo ao qual o inode está se referindo. Isso não funciona - como você descreveu.

    
por 30.04.2013 / 12:25