O documento discute como criar processos em segundo plano (daemons) em PHP usando as extensões PCNTL e POSIX. Apresenta como utilizar a função pcntl_fork() para criar processos filhos e gerenciar sinais entre processos pais e filhos. Explica também como manipular sinais em processos PHP para tratá-los ou ignorá-los.
3. Henrique
Moody
• Desenvolvedor
web
com
foco
em
PHP
desde
2007
• Usuário
assíduo
de
Linux
desde
2008
• Zend
Certified
Engineer
5.3
desde
2011
• Contribui
com
vários
projetos
Open
Source
• Líder
Técnico
• Desenvolvedor
PHP
Senior
3
7. • Em
sistemas
operacionais
Unix-‐like
fork
é
uma
operação
em
que
um
processo
cria
uma
cópia
de
si
mesmo
• Fork
é
uma
forma
de
um
processo
executar
outro
ou
outros
processos
a
partir
de
si
mesmo
• Quando
a
cópia
do
processo
é
criada
essa
cópia
é
chamada
de
processo
filho
tornando
o
processo
original
o
processo
pai
• No
PHP
é
necessária
a
extensão
PCNTL
habilitada
e
extremamente
recomendável
a
extensão
POSIX
também
habilitada
7
8. PCNTL
(Process
Control)
• Deve
ser
habilitada
no
momento
da
compilação
do
PHP
(——enable-pcntl)
• Suportada
apenas
para
sistemas
Unix-‐like
• Não
funciona
em
web
servers
• Cria
e
gerencia
processos
e
sinais
8
9. POSIX
(Portable
Operating
System
Interface)
• Habilitada
por
padrão
na
compilação
do
PHP
• Suportada
apenas
para
sistemas
Unix-‐like
• Fornece
uma
API
padrão
para
desenvolvimento
em
sistemas
Unix-‐like
• Gerencia
processos,
sessões,
grupos,
usuários
e
arquivos
de
sistemas
Unix-‐like
9
10. Funcionamento
• A
função
pcntl_fork()
criará
o
fork
e
retornará
um
valor
diferente
para
cada
processo
(pai
e
filho)
• Caso
pcntl_fork()
retorne
-1
ocorreu
um
erro
no
fork
• Caso
pcntl_fork()
retorne
0
houve
sucesso
no
fork.
O
processo
atual
é
o
filho
• Caso
pcntl_fork()
retorne
um
número
maior
do
que
0
houve
sucesso
no
fork.
O
processo
atual
é
o
pai
e
o
retorno
de
pcntl_fork()
é
o
PID
do
filho
• Nada
impede
um
processo
filho
criar
forks
de
si
mesmo
• Todas
as
variáveis
inicializadas
no
processo
pai
estarão
disponíveis
para
os
filhos
10
11. Forks/pcntl.php
<?php
$pid = pcntl_fork();
if ($pid == -1) {
// Falha na criação do fork
echo 'Falha na criação do fork' . PHP_EOL;
!
} elseif ($pid > 0) {
// Sou o processo pai
echo 'Fork criado com sucesso sob o PID ' . $pid . PHP_EOL;
!
} else {
// Sou o processo filho, em background
mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet');
}
11
12. Forks/pcntl+posix.php
<?php
$pid = pcntl_fork();
if ($pid == -1) {
// Falha na criação do fork
echo 'Falha na criação do fork' . PHP_EOL;
!
} elseif ($pid > 0) {
// Sou o processo pai
echo 'Fork criado com sucesso sob o PID ' . $pid . PHP_EOL;
!
} else {
// Sou o processo filho, em background
if (0 !== posix_getuid()) {
error_log('É necessário ser root para alterar informações do processo');
exit(2);
}
!
!
!
if (! posix_setuid(1000)) {
error_log('Não foi possível definir o usuário do processo como 1000');
exit(3);
}
if (! posix_setgid(1000)) {
error_log('Não foi possível definir o grupo do processo como 1000');
exit(4);
}
mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet');
}
12
14. • Em
sistemas
Unix-‐like,
um
sinal
é
uma
notificação
de
software
a
um
processo
da
ocorrência
de
um
evento
• Um
sinal
é
gerado
pelo
SO
quando
o
evento
que
causa
o
sinal
acontece
• Existem
vários
sinais
que
podem
ser
enviados
para
um
processo,
alguns
deles
podem
ser
manipulados
pela
aplicação
já
outros
apenas
pelo
próprio
SO
• Podemos
enviar
através
da
função
posix_kill()
• Podemos
definir
um
callback
para
manipular
sinais
através
da
função
pcntl_signal()
14
16. Mais
comuns
• SIGHUP:
enviado
quando
o
sessão
(terminal)
do
processo
é
fechada
•
•
•
•
•
•
• Pode
ser
interceptado
SIGINT:
enviado
quando
um
se
pretende
interromper
o
processo
• Pode
ser
interceptado
• Pode
ser
enviado
via
teclado,
com
Control-C,
e
em
alguns
sistemas
com
delete
ou
break
SIGTSTP:
enviado
quando
se
pretende
pausar
o
processo
• Pode
ser
interceptado
• Pode
ser
enviado
via
teclado,
com
Control-Z
SIGCONT:
enviado
quando
se
pretende
despausar
o
processo
após
SIGTSTP
• Pode
ser
interceptado
SIGTERM:
enviado
quando
se
pretende
terminar
o
processo
(amigavelmente).
• Pode
ser
interceptado
SIGQUIT:
enviado
quando
se
pretende
encerrar
o
processo
e
obter
um
dump
de
memória.
• Pode
ser
interceptado
• Pode
ser
enviado
via
teclado,
com
Control-
SIGKILL:
enviado
quando
se
pretende
encerrar
imediatamente
o
processo
• Não
ser
interceptado
16
17. Sinais/envio.php
<?php
!
// Envia um 0 (verifica se o PID é válido ou não)
posix_kill($pid, 0);
!
// Envia um SIGUSR1 (User-defined signal 1)
posix_kill($pid, SIGUSR1);
!
// Envia um SIGSTOP (pausa a execução do processo)
posix_kill($pid, SIGSTOP);
!
// Envia um SIGCONT (continua a execução do processo)
posix_kill($pid, SIGCONT);
!
// Envia um SIGKILL (mata instantâneamente o processo)
posix_kill($pid, SIGKILL);
17
18. Sinais/manipulacao.php
<?php
!
declare(ticks = 1);
function signalHandler($signal)
{
switch ($signal) {
case SIGQUIT;
error_log('Me fecharam com o teclado (Control-)');
exit(1);
case SIGINT:
error_log('Me interromperam com o teclado (Control-C)');
exit(1);
case SIGHUP:
error_log('Fecharam meu terminal');
exit(1);
case SIGTERM:
error_log('Me pediram para me matar');
exit(0);
}
}
!
pcntl_signal(SIGQUIT, 'signalHandler');
pcntl_signal(SIGINT, 'signalHandler');
pcntl_signal(SIGHUP, 'signalHandler');
pcntl_signal(SIGTERM, 'signalHandler');
pcntl_signal(SIGTSTP, 'signalHandler');
pcntl_signal(SIGTSTP, SIG_IGN); // SIG_IGN faz com que SIGTSTP seja ignorado
pcntl_signal(SIGCONT, SIG_IGN); // SIG_IGN faz com que SIGCONT seja ignorado
!
echo 'PID: ' . getmypid() . PHP_EOL;
while (true) {
echo date('Y-m-d H:i:s') . PHP_EOL;
sleep(1);
}
18
20. • Acrônimo
de
Disk
And
Execution
MONitor
(Monitor
de
Execução
e
de
Disco)
• Em
Unix
e
outros
sistemas
operacionais
multi-‐
tarefas
é
um
programa
de
computador
que
roda
de
forma
independente
em
background,
ao
invés
de
ser
controlado
diretamente
por
um
usuário
• Em
um
ambiente
Unix,
o
processo
pai
de
um
daemon
é
normalmente
(mas
nem
sempre)
o
processo
init
(PID=1)
• Alguns
exemplos
de
daemons
são:
MySQL
Server,
Apache
Server,
Nginx
Server,
Cron
• Muitas
vezes,
um
programa
se
torna
um
daemon
através
de
forking
20
22. Passo
a
passo
1. Fork
off
and
die
2. Máscara
de
criação
dos
arquivos
3. Entradas
e
saídas
4. Logging
5. Desligar
sessão
(SID)
6. Working
directory
7. Locking
22
23. Fork
off
and
die
• Você
apenas
criará
o
fork
e
encerrará
imediatamente
o
processo
pai
• O
processo
filho
será
o
daemon,
executando
em
background
23
24. Daemons/fork.php
<?php
$pid = pcntl_fork();
if ($pid == -1) {
echo 'Falha na criação do fork' . PHP_EOL;
exit(2);
!
} elseif ($pid > 0) {
echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL;
exit();
}
!
while (true) {
mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet');
sleep(2);
}
24
25. Máscara
de
criação
dos
arquivos
• Para
garantir
que
você
possa
ler
e
escrever
arquivos
restaure
o
umask
para
o
padrão
do
sistema,
com
umask(0)
25
26. Daemons/fork+umask.php
<?php
$pid = pcntl_fork();
if ($pid == -1) {
echo 'Falha na criação do fork' . PHP_EOL;
exit(2);
!
} elseif ($pid > 0) {
echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL;
exit();
}
!
umask(0);
!
while (true) {
mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet');
sleep(2);
}
26
27. Entradas
e
saídas
• O
daemon
não
possui
interação
com
o
usuário,
portanto
você
não
deve
permitir
que
os
métodos
de
entrada
e
saída
(STDIN,
STDOUT
e
STDERR)
sejam
utilizados
• Você
pode
fechar
STDIN,
STDOUT
e
STDERR,
mas
caso
você
esteja
utilizando
essas
constantes
com
certeza
você
terá
problemas
• Você
também
pode
utilizar
as
funções
ob_*
para
evitar
outputs
27
29. Logging
• Visto
que
não
interação
entre
o
daemon
e
o
usuário,
logs
são
uma
ótima
forma
de
obter
feedback
de
um
daemon
• Você
pode
fazer
logs
em:
‣ Arquivos
‣ Bancos
de
dados
relacionais
‣ Bancos
de
dados
não-‐relacionais
‣ Message
Queue
‣ Syslog
‣…
29
30. Daemons/fork+umask+file_descriptors+logging.php
<?php
$pid = pcntl_fork();
if ($pid == -1) {
echo 'Falha na criação do fork' . PHP_EOL;
exit(2);
!
} elseif ($pid > 0) {
echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL;
exit();
}
!
umask(0);
!
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
!
$fd0 = fopen('/dev/null', 'r');
$fd1 = fopen('/tmp/psd.log', 'a');
$fd2 = fopen('php://stdout', 'a');
!
!
openlog('PSD', LOG_PID | LOG_CONS, LOG_LOCAL0);
while (true) {
syslog(LOG_DEBUG, 'Envio de email iniciando');
$sent = mail('vagrant@localhost', 'Lorem ipsum', 'Lorem ipsum dolor sit amet');
if (true === $sent) {
syslog(LOG_DEBUG, 'Envio de email terminado sucesso');
continue;
}
syslog(LOG_ERR, 'Falha ao enviar email');
sleep(2);
}
closelog();
30
31. Desligar
sessão
(SID)
• Mesmo
que
o
processo
filho
seja
executado
em
background,
não
dependendo
do
processo
pai,
eles
estão
na
mesma
sessão
• Quando
a
sessão
terminar
(o
terminal
fechado,
por
exemplo),
o
sistema
matará
o
processo
filho
• A
função
posix_setsid()
cria
uma
nova
sessão
para
o
processo
filho,
desvinculando-‐o
do
processo
pai
e
sua
sessão
• O
processo
filho
passa
a
ter
o
init
(processo
inicial
que
carrega
todos
os
outros
processos
do
sistema)
como
processo
pai
31
32. Daemons/fork+umask+file_descriptors+logging+detach_sid.php
<?php
$pid = pcntl_fork();
if ($pid == -1) {
echo 'Falha na criação do fork' . PHP_EOL;
exit(2);
!
} elseif ($pid > 0) {
echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL;
exit();
}
!
umask(0);
!
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
!
$fd0 = fopen('/dev/null', 'r');
$fd1 = fopen('/tmp/psd.log', 'a');
$fd2 = fopen('php://stdout', 'a');
!
openlog('PSD', LOG_PID | LOG_CONS, LOG_LOCAL0);
!
if (posix_setsid() < 0) {
syslog(LOG_ERR, 'Não foi possível desvincular processo de sua sessão');
exit(2);
}
!
while (true) { /** Payload **/ }
closelog();
32
33. Working
directory
• O
filho
herda
o
working
directory
do
pai
• Este
working
directory
pode
ser
um
volume
montado
que
pode
ser
desmontado
em
algum
momento
• Para
desmontar
um
volume
o
sistema
irá
matar
qualquer
processo
que
ainda
está
usando
o
diretório
33
34. Daemons/fork+umask+file_descriptors+logging+detach_sid+chdir.php
<?php
$pid = pcntl_fork();
if ($pid == -1) {
echo 'Falha na criação do fork' . PHP_EOL;
exit(2);
!
} elseif ($pid > 0) {
echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL;
exit();
}
!
umask(0);
!
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
!
$fd0 = fopen('/dev/null', 'r');
$fd1 = fopen('/tmp/psd.log', 'a');
$fd2 = fopen('php://stdout', 'a');
!
openlog('PSD', LOG_PID | LOG_CONS, LOG_LOCAL0);
!
if (posix_setsid() < 0) {
syslog(LOG_ERR, 'Não foi possível desvincular processo de sua sessão');
exit(2);
}
!
chdir(__DIR__);
!
while (true) { /** Payload **/ }
closelog();
34
35. pidfile
• Contém
o
PID
do
daemon
• Impede
que
o
daemon
seja
executado
mais
de
uma
vez
35
39. • Muito
utilizado
no
processamento
de
filas
quando
você
precisa
de
processos
concorrentes
• Um
processo
pode
criar
outros
processos
e
delegar
tarefas
para
cada
um
deles
• Esse
recurso
muitas
vezes
é
confundido
com
multi-‐threading,
mas
não
é
isso.
O
PHP
não
possui
suporte
a
este
recurso
mas
existe
uma
extensão
PECL
para
isso
• Geralmente
os
processos
pai
são
daemons
sendo
seus
filhos
workers
• Você
não
pode
alterar
o
SID
dos
filhos
pois
você
precisa
deles
na
mesma
sessão
do
processo
pai
39
40. Spawn/exemplo.php
<?php
$pid = pcntl...// Fluxo normal do daemon
!
$childrenLimit = 10;
$childrenPids = array();
while (true) {
if (count($childrenPids) >= $childrenLimit) {
$firstChildPid = array_shift($childrenPids);
pcntl_waitpid($firstChildPid, $status);
}
!
!
!
!
$childPid = pcntl_fork();
if ($childPid == -1) {
syslog(LOG_ERR, 'Falha ao criar filho');
continue;
}
if ($childPid > 0) {
$childrenPids[] = $childPid;
continue;
}
syslog(LOG_DEBUG, 'Envio de email iniciando');
$sent = mail('vagrant@localhost', 'Lorem ipsum', 'Lorem ipsum dolor sit amet');
if (true === $sent) {
syslog(LOG_DEBUG, 'Envio de email terminado sucesso');
exit(0);
}
syslog(LOG_ERR, 'Falha ao enviar email');
exit(3);
}
closelog();
40
42. • Um
processo
zombie
é
um
processo
que
já
foi
completamente
executado
mas
ainda
se
encontra
na
tabela
de
processos
do
SO,
permitindo
que
o
processo
que
o
criou
leia
o
seu
valor
de
saída
• Quando
um
processo
termina,
a
memória
a
ele
associada
é
libertada,
no
entanto
a
informação
sobre
esse
processo
continua
disponível,
embora
ele
já
não
exista
• Normalmente
os
processos
zombie
não
duram
muito
tempo
já
que
o
sinal
SIGCHLD
é
emitido
quando
ele
entra
nesse
estado,
possibilitando
ao
processo
pai
saber
quando
isso
acontece
para
ler
as
informações
necessárias
• Se
o
processo
pai
explicitamente
ignora
o
SIGCHLD
definindo
seu
manipulador
como
SIG_IGN
todos
as
informações
de
término
dos
processos
filhos
serão
descartadas
e
os
processos
zombies
continuarão
na
tabela
42
45. • Cada
processo
possui
um
contexto
de
execução
próprio.
Um
processo
não
tem
conhecimento
do
contexto
de
outro
processo
sendo
assim
os
processos
não
conseguem
transferir
informação
entre
si
• Inter-‐Process
Communication
(IPC),
é
o
grupo
de
mecanismos
que
permite
aos
processos
transferirem
informação
entre
si
• Usando
IPC
um
processo
pai
consegue
obter
informações
precisar
de
seus
filhos
• Para
IPC
podemos
utilizar:
‣ Arquivos
‣ Filas
de
mensagens
‣ Memória
Compartilhada
‣ Sinais
‣ Par
de
Sockets
‣…
45
46. Arquivos
• Você
pode
escrever
dados
em
um
processo
e
ler
em
outro
processo,
desde
que
ambos
tenham
permissão
de
leitura
• Nome
do
arquivo
deve
ser
único
46
47. IPC/file.php
<?php
!
$filename = '/tmp/' . getmypid() . '.ipc';
if (! is_file($filename)) {
touch($filename);
}
!
$dataWritten = 'PHP e seus Demônios';
if (false === file_put_contents($filename, $dataWritten)) {
echo 'Falha ao gravar dados no arquivo' . PHP_EOL;
exit(2);
}
!
$dataGiven = file_get_contents($filename);
if (false === $dataGiven) {
echo 'Falha ao ler dados no arquivo' . PHP_EOL;
exit(3);
}
!
echo 'Dado lido no arquivo: ' . $dataGiven . PHP_EOL;
!
if (! unlink($filename)) {
echo 'Falha ao tentar remover o arquivo' . PHP_EOL;
exit(3);
}
47
48. Memória
compartilhada
• É
um
fácil
caminho
para
usar
funções
que
permitem
o
PHP
ler,
escrever,
criar
e
deletar
segmentos
de
memória
compartilhada
UNIX
• O
PHP
possui
duas
API’s,
as
funções
shmop_*
e
shm_*:
• Para
habilitar
as
funções
shmop_*
é
preciso
compilar
o
PHP
com
a
opção
--enable-shmop
do
configure
• Para
habilitar
as
funções
shm_*
é
preciso
compilar
o
PHP
com
a
opção
--enable-sysvshm
do
configure
• Funciona
basicamente
com
uma
chave,
por
ela
você
pode
ler
e
escrever
dados
na
memória
• Utilize
o
comando
ipcs
para
monitorar
os
seguimentos
criados
e
ipcrm shm ID
para
remover
seguimentos
(você
também
pode
usar
ipcmk
para
criar
seguimentos)
48
49. IPC/shmop.php
<?php
!
$key = getmypid();
$flag = 'c';
$permission = 0644;
$memorySize = 1024;
!
$shmId = shmop_open($key, $flag, $permission, $memorySize);
if (! $shmId) {
echo 'Não foi possível criar o segmento de memória' . PHP_EOL;
exit(1);
}
!
$stringWritten = 'PHP e seus demônios';
$shmBytesWritten = shmop_write($shmId, $stringWritten, 0);
if ($shmBytesWritten != strlen($stringWritten)) {
echo 'Não foi possível gravar o dado e com seu tamanho correto' . PHP_EOL;
exit(2);
}
!
$stringRead = shmop_read($shmId, 0, $memorySize);
if (! $stringRead) {
echo 'Não foi possível ler o dado na memória compartilhada' . PHP_EOL;
exit(2);
}
!
echo 'Dado lido na memória compartilhada foi: ' . $stringRead . PHP_EOL;
!
if (! shmop_delete($shmId)) {
echo 'Não foi possível marcar o bloco de memória compartilhada para remoção';
}
!
shmop_close($shmId);
49
50. IPC/shm.php
<?php
!
$key = getmypid();
$permission = 0644;
$memorySize = 1024;
!
$shmId = shm_attach($key, $memorySize, $permission);
if (! $shmId) {
echo 'Falha ao criar o segmento de memória' . PHP_EOL;
exit(1);
}
!
$stringWritten = 'PHP e seus demônios';
if (! shm_put_var($shmId, 1, $stringWritten)) {
echo 'Falha ao gravar o dado na memória compartilhada' . PHP_EOL;
exit(2);
}
!
if (! shm_has_var($shmId, 1)) {
echo 'Nenhum dado na chave 1 foi encontrado na memória' . PHP_EOL;
exit(2);
}
!
$stringRead = shm_get_var($shmId, 1);
if (! $stringRead) {
echo 'Falha ao ler o dado da chave 1 na memória compartilhada' . PHP_EOL;
exit(2);
}
!
echo 'Dado lido na memória compartilhada foi: ' . $stringRead . PHP_EOL;
!
if (! shm_remove($shmId)) {
echo 'Falha ao remover do bloco de memória compartilhada';
}
!
if (! shm_detach($shmId)) {
echo 'Falha ao se desconectar do bloco de memória compartilhada';
}
50
51. Filas
de
mensagens
• O
PHP
possui
suporte
a
filas
de
mensagens
do
• Para
habilitar
as
funções
msg_*
é
preciso
compilar
o
PHP
com
a
opção
--enable-sysvmsg
do
configure
• Utilize
o
comando
ipcs
para
monitorar
os
seguimentos
criados
e
ipcrm msg ID
para
remover
seguimentos
(você
também
pode
usar
ipcmk
para
criar
seguimentos)
51
52. IPC/msg.php
<?php
!
$key = getmypid();
$messageQueueId = msg_get_queue($key);
!
$messageSent = 'PHP e seus demônios';
$messageWasSent = msg_send($messageQueueId, 2, $messageSent);
if (! $messageWasSent) {
echo 'Falha ao enviar mensagem' . PHP_EOL;
exit(2);
}
!
if (! msg_receive($messageQueueId, 2, $msgType, 1024, $messageReceived,
true, 0, $error)) {
echo 'Falha ao ler mensagem' . $error . PHP_EOL;
exit(3);
}
echo 'Mensagem recebida: ' . $messageReceived . PHP_EOL;
!
if (! msg_remove_queue($messageQueueId)) {
echo 'Falha ao remover fila de mensagens'. PHP_EOL;
exit(3);
}
52
53. Par
de
sockets
• Dois
sockets
conectados
armazenados
em
um
array
• Conexão
de
duas
vias,
as
mensagens
são
entregues
no
mesmo
instante
53
54. IPC/msg.php
<?php
!
$sockets = array();
!
if (false === socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets)) {
echo 'Falha ao criar par de sockets: ' . socket_strerror(socket_last_error()) . PHP_EOL;
}
!
$pid = pcntl_fork();
if ($pid == -1) {
echo 'Falha na criação do fork' . PHP_EOL;
} elseif ($pid > 0) {
!
!
!
socket_close($sockets[0]);
$messageWritten = 'Mensagem enviada pelo processo pai';
if (false === socket_write($sockets[1], $messageWritten, strlen($messageWritten))) {
echo 'Falha ao escrever dados no socket: ' . socket_strerror(socket_last_error($sockets));
exit(3);
}
$messageGiven = socket_read($sockets[1], 1024, PHP_BINARY_READ);
echo 'Mensagem no processo pai: ' . "t" . $messageGiven . PHP_EOL;
socket_close($sockets[1]);
!
} else {
!
!
!
socket_close($sockets[1]);
$messageWritten = 'Mensagem enviada pelo processo filho';
if (false === socket_write($sockets[0], $messageWritten, strlen($messageWritten))) {
echo 'Falha ao escrever dados no socket: ' . socket_strerror(socket_last_error($sockets));
exit(3);
}
$messageGiven = socket_read($sockets[0], 1024, PHP_BINARY_READ);
echo 'Mensagem no processo filho: ' . "t" . $messageGiven . PHP_EOL;
socket_close($sockets[0]);
}
54
57. • Não
existe
garbage
collection,
o
processo
principal
não
morre
• Utilize
as
funções
gc_enable()
e
gc_collect_cycles()
• O
PHP
possui
um
cache
padrão
de
arquivos
abertos
(em
memória)
isso
pode
prejudicar
a
performance
do
daemon,
utilize
clearstatcache()
para
remover
esse
cache
• Utilizar
IPC
sem
limpar
os
dados
corretamente
pode
ocasionar
uma
série
de
problemas
57