You can clone with
HTTPS or Subversion.
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.
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]
usleep(): Number of microseconds must be greater than or equal to 0
All files in the library are current. This is on a 64-bit machine running PHP 5.2.13, FWIW.
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.
@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.
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 :-/
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.
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$this->sleepIncrement));
$outerSleepInt = min(200000, $outerSleepInt );
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;
$runningCurrent = $this->running;
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.
Casting value to usleep to int.
Closed by 360e37e.