Prevent closing a stream socket on parent window with child fork

I have a worker that covers new jobs with pcntl_fork()

, I would like to reuse the same connection in every child without having to re-connect every time in every child, the goal is to get a huge performance boost.

  • In the parent, I connect to the SMTP service and then disconnect the child.
  • The first child can successfully use the SMTP stream and can send a message.
  • The socket is automatically closed when the child runs out. I don't call any closely related functions nor destructors, you can see in the attached example repo.
  • The parent or next child can then use the open socket more.

I want to prevent number 3. so that the next child can reuse the socket without having to reconnect, as you know that SMTP is frequent and takes a while to reconnect. The SMTP server could be sendmail / sendgrid / Gmail, I tried multiple providers and the problem is my PHP, not the SMTP protocol.

I read that signals can cause the stream to close. Is there a way to prevent this.

what are my options?

I am using PHPMailer , I removed the close from the destructor . I activated SMTPKeepAlive

but didn't help as you can see in the attached example repo. If I am using PHP 5.4

Update 1

I have added sample code to this public repo: https://github.com/pentium10/php_stream_socket_test and you can check the post folder http://www.dispostable.com/inbox/test/

You can find the SMTP output and response in the README file of the repo. I confirm that by removing anything from the fork / child / exit call the example works and sends multiple messages one after the other.

+3


source to share


1 answer


After some research in the code you provided, it looks like your problem occurs when you enable TLS.

If you disable the following line:

$mail->SMTPSecure = 'tls';

      

Your code will work as expected (as soon as your SMTP server accepts unsecured connections).



So this is definitely not a socket, but a fork issue , but probably a violation of the TLS protocol .

If you try to send an RSET verb (like call $mail->getSMTPInstance()->reset();

before call email()

), the error when sending the second mail becomes clearer:

2014-11-04 00:23:18 SMTP ERROR: RSET command failed:
2014-11-04 00:23:18 SMTP NOTICE: EOF caught while checking if connected

      

I am not a crypto specialist so I cannot get any further. But I'm pretty sure the resource used by stream_socket_client (and the wrapped stream_socket_enable_crypto ) holds some contextual information needed to execute the next TLS transaction. After the email from the first child is sent, the resource context is updated in child memory, but not in the parent. So when you try to send another email using the old context, TLS is aborted.

+2


source







All Articles