immobiliare / ApnsPHP

ApnsPHP: Apple Push Notification & Feedback Provider
BSD 3-Clause "New" or "Revised" License
1.44k stars 452 forks source link

Stopped working with OpenSSL changes in PHP 5.6.7 #84

Open shawn-digitalpoint opened 9 years ago

shawn-digitalpoint commented 9 years ago

Times out with the fread() function in the ApnsPHP_Push->_readErrorMessage() method with the changes PHP 5.6.7 made. Reverting back to PHP 5.6.6 (same compile options) and everything back to working.

Not sure it makes a difference, but it's with the OpenSSL 1.0.2a libs.

Haven't had time to dig too much into the underlying issue, but seeing how PHP 5.6.7 made a bunch of changes to OpenSSL and how it handles timeouts, I wonder if they introduced a bug. http://php.net/ChangeLog-5.php#5.6.7

ghost commented 9 years ago

Reproducable with PHP 5.6.7 and 5.5.23.

TimE90 commented 9 years ago

Same here… socket timeout slows down the stream to 60seconds per read…

Tried to set timeout socket to a short time but doesn't affect when calling via CGI. duccio, we need a urgent fix here please :)

PHP fixed bug #61285, #68329, #68046, #41631 (encrypted streams don't observe socket timeouts).

aporat commented 9 years ago

Looks like rolling back to PHP 5.6.6 is the best alternative right now

sshilko commented 9 years ago

Same issue with 5.5.23 upgrade from 5.5.22

Any PPA's for 5.5.22 ?? . deb.sury is 5.5.23 :( ubuntu 12.04

anyone, any workarounds?

Full 5.5.22 -> 5.5.23 diff here

https://launchpadlibrarian.net/201114140/php5_5.5.22%2Bdfsg-1%2Bdeb.sury.org~precise%2B1_5.5.23%2Bdfsg-1%2Bdeb.sury.org~precise%2B2.diff.gz

Original git merge thread

https://github.com/php/php-src/pull/971

sshilko commented 9 years ago

php issue submitted

https://bugs.php.net/bug.php?id=69393

EugenMayer commented 9 years ago

could that also affect PECL over proxy? https://pecl.php.net/package-changelog.php?package=pecl_http&release=2.4.3

sshilko commented 9 years ago

@EugenMayer not sure, not using that package. try changing the

ini_get("default_socket_timeout") 

value, it uses that timeout for socket operations.. and check difference if using 5.5.22 and 5.5.23

i'am using this workaround atm

ini_ini("default_socket_timeout", 1) 

on dev machines where i can upgrade, not a workaround for production tho.

sshilko commented 9 years ago

Though this bug has been fixed upstream, it wasn't discovered until 5.5.23 and 5.6.7 were already in the RC stage and couldn't be included in these releases. The next set of bugfix releases resolves this issue.

hi everyone, the bug was confirmed and the fix is in upstream, everyone interested in ApnsPHP invited to use https://packagist.org/packages/sshilko/backq https://github.com/sshilko/backq as a solution to dispatch push notifications, its stable and in production.

beeradmoore commented 9 years ago

Issue still occurs in 5.5.24. EDIT: Can confirm for the issue I was seeing (100% CPU for 60sec while sending to sandbox server) that it did not happen when I downgraded to 5.5.22.

sshilko commented 9 years ago

5.6.8 and 5.5.24 were in RC already, fix expected in 5.5.25.. look into comments from dev On Apr 19, 2015 12:45 PM, "ytn3rd" notifications@github.com wrote:

Issue still occurs in 5.5.24.

— Reply to this email directly or view it on GitHub https://github.com/duccio/ApnsPHP/issues/84#issuecomment-94262815.

beeradmoore commented 9 years ago

I did. "it wasn't discovered until 5.5.23 and 5.6.7 were already in the RC stage and couldn't be included in these releases. The next set of bugfix releases resolves this issue."

Had assumed that when they say the next set of bugfix release would mean 5.5.24 which it clearly isn't fixed in.

sshilko commented 9 years ago

Fix Bug #69402: Reading empty SSL stream hangs until timeout https://bugs.php.net/bug.php?id=69402

believe thats the fix https://git.php.net/?p=php-src.git;a=commit;h=81f356b4aea79cd8f86e16096c7ccfbc455bfc3c

and the comment says

This is now fixed upstream in 5.5 and 5.6 branches. 
The RC period has already begun for 5.5.24 and 5.6.8 
so this fix will not be reflected in releases
until 5.5.25 and 5.6.9. 
beeradmoore commented 9 years ago

Ah, gotya. Was reading the bugreport you had posted earlier. Your new comment was not there at the time of writing. Good to know it'll all be fixed for 5.5.25 though.

"php issue submitted https://bugs.php.net/bug.php?id=69393"

iquito commented 9 years ago

I experience this problem aswell - but I cannot easily downgrade my PHP version. How do you work around this problem? For now ApnsPHP just does not work as long as this bug is still around. Setting socket timeout values has no effect, so what else can be done?

sshilko commented 9 years ago

i mentioned a workaround above, u can control "how long it will be stuck" reading with

ini_ini("default_socket_timeout", 1) 

this way it will be stuck for 1 second each time it tries to read from socket (when bug happends).

iquito commented 9 years ago

I already did that - it does not work. The script is still permanently stuck.

iquito commented 9 years ago

No timeout seems to actually have an effect - without explicitely killing processes they are running forever, never stopping and all using 100% CPU. I have actually had a CPU load of 20000 within 24 hours just because of all the cron jobs calling ApnsPHP.

sshilko commented 9 years ago

do it before you connect, not before you execute read from stream.. worked for me at 5.5.23 and currently works too

//5.5.23-1+deb.sury.org~precise+2
//execute before initializing stream_socket_client or use 4th argument of stream_socket_client
ini_ini("default_socket_timeout", 1) 

/*
resource stream_socket_client ( string $remote_socket [, int &$errno [, string &$errstr [, float $timeout = ini_get("default_socket_timeout") [, int $flags = STREAM_CLIENT_CONNECT [, resource $context ]]]]] )
*/

$socket = stream_socket_client($url,
                               $error1,
                               $error2,
                               $timeoutValueInSeconds,
                               STREAM_CLIENT_CONNECT,
                               $streamContext);

stream_set_blocking($socket, 0);
stream_set_write_buffer($socket, 0);
stream_set_read_buffer($socket, 0);

and yeah.. ads :)

use https://github.com/sshilko/backq

iquito commented 9 years ago

That is what I did - I called the ini_set command at the very beginning of the script, before anything happens at all. Yet the cron script just goes to 100% CPU and stays there forever - even after 12 hours it is still going, when every possible timeout should have been reached.

sshilko commented 9 years ago

works for me, i'am setting 2 seconds timeout as an stream_socket_client 4th argument, and seeing it work (taking 2 seconds, instead of 1 second in 5.5.22 as should be according to stream_set_timeout)

$ time php test.php
Sending 172 bytes over tls://gateway.sandbox.push.apple.com:2195:
Socket state:
Array
(
    [stream_type] => tcp_socket/ssl
    [mode] => r+
    [unread_bytes] => 0
    [seekable] => 
    [timed_out] => 
    [blocked] => 
    [eof] => 
)
stream_set_timeout timeout set: 1 second
Has errors: string(0) ""

real    0m2.685s
user    0m0.836s
sys     0m1.708s
iquito commented 9 years ago

Nope, setting the stream_socket_client connect timeout does not work either - that's a connect timeout, so it should not have any effect on reading from a remote host anyway, as the connection is not the problem. "default_socket_timeout" should have been it, but that definitely does not work, unfortunately.

The only thing which works and still lets the script run it course is by commenting out the contents of _readErrorMessage() in ApnsPHP_Push - which disables all error handling, but at least the servers are not completely overloaded. Having a server load of 20000 really is quite frightening.

jakobjw commented 9 years ago

All the workarounds seem to work only if there is no "invalid" (unregistered) APNS token contained in the queue. To me it seems that it works till the first invalid token, all receivers with tokens after that one don't receive messages. Although the log output of ApnsPHP looks completely successful.

Maybe the reason is that the APNS server wants to send an error response after an invalid token and, from this point on, the ApnsPHP workaround hinders from successfully communicating with the server.

sshilko commented 9 years ago

apple doc clearly states that messages after error would not be processed as i remember. read apple docs. thats why there are disconnect+resend logic in apns.

maybe iam wrong ') On May 6, 2015 7:50 PM, "jakobjw" notifications@github.com wrote:

All the workarounds seem to work only if there is no "invalid" (unregistered) APNS token contained in the queue. To me it seems that it works till the first invalid token, all receivers with tokens after that one don't receive messages. Although the log output of ApnsPHP looks completely successful.

Maybe the reason is that the APNS server wants to send an error response after an invalid token and, from this point on, the ApnsPHP workaround hinders from successfully communicating with the server.

— Reply to this email directly or view it on GitHub https://github.com/duccio/ApnsPHP/issues/84#issuecomment-99551541.

sshilko commented 9 years ago

also the workaround was to prevent the 100%cpu load infinitely/60sec . not really to fix the logic. tho iam sending the messages 1by1 in backq probably thats why fix workex for me. On May 6, 2015 7:50 PM, "jakobjw" notifications@github.com wrote:

All the workarounds seem to work only if there is no "invalid" (unregistered) APNS token contained in the queue. To me it seems that it works till the first invalid token, all receivers with tokens after that one don't receive messages. Although the log output of ApnsPHP looks completely successful.

Maybe the reason is that the APNS server wants to send an error response after an invalid token and, from this point on, the ApnsPHP workaround hinders from successfully communicating with the server.

— Reply to this email directly or view it on GitHub https://github.com/duccio/ApnsPHP/issues/84#issuecomment-99551541.

mfrr1118 commented 9 years ago

For me that workaround does the same as commenting the fread line. It disconnects after the first invalid token is found.

jakobjw commented 9 years ago

My problem is that I have a list of about 3000 receiver tokens and this list also contains invalid tokens which I don't know. I suppose that sending them 1by1 would be too inefficient. Do you have any suggestions for me?

sshilko commented 9 years ago

jakobjw 1by1 not too inefficient in 1 thread, but if u have 100 workers running should not be an issue, isnt it.

aporat commented 9 years ago

Seems that the latest PHP 5.6.9 release solves this issue.

rwforsythe commented 9 years ago

Ditto for PHP 5.5.25; seems like it now works. Phew.

sshilko commented 9 years ago

yes, seems so http://php.net/ChangeLog-5.php#5.5.25

Fixed bug #69402 (Reading empty SSL stream hangs until timeout).

Didnt tested yet tho, https://launchpad.net/~ondrej/+archive/ubuntu/php5 updated just 2 days ago