Skip to content

ongoing fails of usleep() ... actually fixed now... #72

jgberg opened this Issue Jun 28, 2010 · 10 comments

3 participants

jgberg commented Jun 28, 2010

In the latest code, there is an attempt to prevent calling usleep() with a value less than 1 as a means to ward off PHP notices of bad values passed to usleep... However, this code doesn't fully address the problem; we've been seeing errors still...

But we do have a fix...
1. the value passed to usleep() should be provided with a maximum value, which we picked as 200,000 or 20 seconds (not just prevented to be < 1)
2. the value passed to usleep() must be forced to be an int... we did; usleep( intval( $sleepAmt) );

We believe that there is a bug in PHP 5.2.x that if usleep() is passed floats (probably big floats (hence the max above) ) that it will think it's being passed a value < 1, and causes a php Notice to fire. The changes above seem to address this problem.

jmathai commented Jul 19, 2010

Thanks for this. I'll put an upper bound on the usleep.


My issue may be related to this, but my values are significantly less than 0. Here's a stack trace of the Warning:

WARNING: usleep(): Number of microseconds must be greater than or equal to 0 in /var/www/_inc/Epi/EpiCurl.php on line 69


#0  usleep(-762007357879920640) called at [/var/www/_inc/Epi/EpiCurl.php:69]
#1  EpiCurl->getResult(Resource id #27) called at [/var/www/_inc/Epi/EpiCurl.php:151]
#2  EpiCurlManager->__get(data) called at [/var/www/_inc/Epi/EpiTwitter.php:212]
#3  EpiTwitterJson->__get(responseText) called at [/var/www/_inc/Epi/EpiTwitter.php:119]
#4  EpiTwitter->request(GET, /statuses/user_timeline.json, Array ([user_id] => 17909625)) called at [/var/www/_inc/Epi/EpiTwitter.php:36]
#5  EpiTwitter->get(/statuses/user_timeline.json, Array ([user_id] => 17909625)) called at [/var/www/CRON_FILES/collectOutsideStats.php:30]

All files in the library are current. This is on a 64-bit machine running PHP 5.2.13, FWIW.

Thanks! :-)

jmathai commented Aug 11, 2010

Just wanted to update the bug :).

I'm all for putting an upper bound on the microseconds for the usleep. However, I don't know what that value should be. I could set one arbitrarily, but the sleep increment of 1.1 was derived at by putting the library under a decent load test.

jmathai commented Aug 11, 2010

@PureForm, are you using the latest code from github? There's a max(1, *) value that should ensure that the value passed into usleep is >= 1. Unless it's related to floats.

jgberg commented Aug 12, 2010

jmathai, just be clear it's not fixed fix max() alone ... but the coercion to int to...


Yeah, I'm using the latest code. I'm wondering how that got through the max() function. I turned off APC a while back due to it having some segfault issues on RHEL 4. It only appeared about 10 times in my error logs in a one-minute period then went away... Not sure here :-/

jmathai commented Sep 19, 2010

While converting to an int may make the library work it bypasses the sleeping logic altogether. as it's incremented by a decimal value. so 1*1.1 always becomes 1. This works but the sleep logic was put in place to help the library under heavy load.

So, I'm a little reluctant to solve this problem that way. The original bug report was that the sleep value is < 1 which i don't see as being possible due to the max function.

jgberg commented Sep 19, 2010

I'm not saying convert to an int and preserve that value. I'm saying do the math as a float and preserve that value, so that 11.1 logic continues, but just convert that float to an int for the single call to usleep() ...

Here's my hack in EpiCurl::getResults():
while($this->running && ($this->execStatus == CURLM_OK || $this->execStatus == CURLM_CALL_MULTI_PERFORM))
usleep( intval($outerSleepInt) );
$outerSleepInt = max(1, ($outerSleepInt
$outerSleepInt = min(200000, $outerSleepInt );
$ms=curl_multi_select($this->mc, 0);
if($ms > 0)
$this->execStatus = curl_multi_exec($this->mc, $this->running);
usleep( intval($innerSleepInt) );
$innerSleepInt = max(1, ($innerSleepInt*$this->sleepIncrement));
$innerSleepInt = min(200000, $innerSleepInt );
$innerSleepInt = 1;
return $this->responses[$key];
$runningCurrent = $this->running;

jmathai commented Sep 20, 2010

Ok, not sure why it's been so hard to get to this point but I think I understand what you're saying now. -- thanks for the persistence.

jmathai commented Sep 25, 2010

Casting value to usleep to int.
Closed by 360e37e.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.