Falha de segmentação PHP ao usar mais de 128M

2

Eu tenho uma instalação do SugarCRM. É pesado na memória, que é uma questão separada para lidar. Enquanto isso, qualquer página que tente usar mais de 128 milhões de memória, resulta no processo do Apache (mod_php) interrompido com uma falha de segmentação:

[notice] child pid 6852 exit signal Segmentation fault (11)

Se eu definir o limite de memória do PHP para 128M, nunca receberei o sinal 11; Acabei de receber o erro normal do PHP dizendo que não é possível alocar mais memória. Se eu definir o limite de memória do PHP para mais de 128M - mesmo que ligeiramente - então qualquer processo que entrar nessa memória causa a falha de segmentação e uma tela branca / conexão quebrada para o usuário.

Estou usando o PHP 5.3.21 em um servidor CentOS 6.2 com o repositório Atomic. É um servidor de produção, portanto, não há compiladores presentes, portanto, não é possível recompilar os processos do Apache para fazer os despejos principais.

Temos o APC 3.1.13 instalado e precisamos disso para alguns sites. É (acredito) desativado para o meu site SugarCRM.

Não sei quais outros detalhes são necessários para diagnosticar isso? Eu estou esperando que haja algumas coisas óbvias que eu possa olhar, se alguém aqui encontrou algo similar. O que acontece com o 128M que causa a falha se o uso de memória exceder esse valor?

Editar:

O enredo engrossa. Este script de teste é executado, com 256M configurado como memory_limit, até que o processo do PHP fique sem memória por volta de 256M. Não causa uma falha de segmentação; ele é executado e termina com graça:

<?php phpinfo();

$array = array();

while (true) {
    $array[] = str_pad('', 1024*512, '0');
    echo " " . memory_get_usage();
}

Portanto, estamos fadados a algo que o SugarCRM faz (um aplicativo PHP / MySQL simples) que causa a falha de segmentação, mas somente quando o memory_limit é configurado para mais de 128MBytes e é atingida uma página que excede o limite de 128MByte. Isso vai ser muito complicado para diminuir. Se é causada por uma linha específica de código PHP ou construída na aplicação, ou é o resultado de toda uma sequência de coisas que a aplicação faz (eg fazendo coisas que ativam o garbage collector para começar a arrumar, ou desfazendo objetos que tenho conexões de banco de dados abertas, ou todos os tipos de coisas que eu poderia imaginar) para acionar um bug do PHP, não está claro.

Eu não ficaria surpreso se isso se tornar um problema no servidor, talvez com uma solução de programação.

Editar 2:

Agora posso reproduzir facilmente a falha de segmentação:

<?php 
function test1() {
    static $instance = 0;
    $instance += 1;
    echo " $instance ";
    test1();
}
test1();

Uma falha seg pode ser esperada fazendo esse tipo de coisa. Pessoalmente, eu espero que ele seja tratado pelo PHP um pouco melhor, mas talvez esse seja o curso para PHP? Contanto que o memory_limit esteja configurado para 128M, ele parece ser bem gerenciado. Quando eu configuro para 256M, o seg falha.

Ao seguir pela execução do aplicativo, passo a passo, parece estar entrando em um loop recursivo conforme grava seus arquivos de cache iniciais (o SugarCRM faz muito cache). É difícil de seguir, mas eu suspeito que isso é causado por falta de tratamento de erros - ele grava um arquivo e apenas espera que o arquivo esteja lá, sem verificar os resultados de fopen (). Nós estamos rodando o SELinux, e agora estou me perguntando se isso está atrapalhando - certamente tem em outros aplicativos, onde o PHP is_writeable () diz "bem, você pode escrever um arquivo aqui", mas quando isso acontece, o SELinux entra em ação an diz: "de jeito nenhum você está escrevendo esse arquivo aqui". O SugarCRM verifica a primeira pergunta e nem sempre verifica se realmente foi bem-sucedida.

Então - eu espero que isso possa ser considerado uma questão de programação agora? Ainda é um problema com o servidor e o PHP não está jogando bem um com o outro em minha mente, mas correções de bug adequadas no SugarCRM devem funcionar em torno disso.

    
por Jason 30.01.2013 / 13:29

2 respostas

2

Isso é o mais perto que eu cheguei, e provavelmente até onde eu vou chegar agora:

  1. O SugarCRM não verifica erros em seus comandos de gravação de arquivos corretamente, portanto, às vezes, não sabe que um arquivo não foi gravado.

  2. O SugarCRM grava muitos arquivos de cache quando constrói seus arquivos de tempo de execução na primeira execução.

  3. Ao construir esses arquivos de cache, algumas permissões incorretas resultaram em alguns arquivos não sendo gravados corretamente.

  4. Os arquivos perdidos colocam o SugarCRM em um loop recursivo sem fim, com o método de gravação em cache chamando-se recursivamente.

  5. Com o memory_limit do PHP definido como maior que 128M, em vez de relatar que o processo ficou sem memória, as falhas de segmentação. Abaixo de 128M e o processo do PHP é morto de forma mais limpa. Eu só posso supor que este é um bug do PHP, ou um bug em um plugin (não APC). De onde vem o valor de 128M, não sei.

Eu o consertei reinstalando o SugarCRM, configurando todos os arquivos e diretórios para o 777, e então ele funciona. As permissões agora precisarão ser recuperadas até que eu encontre onde está falhando. Um ticket para o SugarCRM (community edition) será útil, assim como um ticket para o PHP (embora eu espere que eu não seja capaz de dar a eles os core dumps que eles inevitavelmente solicitam, então isso pode ser um beco sem saída).

Obrigado por todas as suas sugestões. Espero que isso seja útil para os outros.

    
por 01.02.2013 / 02:15
1

Livre-se da APC e substitua-a por uma das suas alternativas eAccelerator ou XCache. Tem sido a causa de anos de acidentes misteriosos semelhantes a isso em meus ambientes de produção, todos os quais desapareceram assim que a APC se foi.

    
por 30.01.2013 / 20:27