Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

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

Closed
jgberg opened this Issue · 10 comments

3 participants

@jgberg

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
Owner

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

@PureForm

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

TRACE:

#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
Owner

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
Owner

@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

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

@PureForm

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
Owner

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

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 );
$ms=curl_multi_select($this->mc, 0);
if($ms > 0)
{
do{
$this->execStatus = curl_multi_exec($this->mc, $this->running);
usleep( intval($innerSleepInt) );
$innerSleepInt = max(1, ($innerSleepInt*$this->sleepIncrement));
$innerSleepInt = min(200000, $innerSleepInt );
}while($this->execStatus==CURLM_CALL_MULTI_PERFORM);
$innerSleepInt = 1;
}
$this->storeResponses();
if(isset($this->responses[$key]['data']))
{
return $this->responses[$key];
}
$runningCurrent = $this->running;
}

@jmathai
Owner

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
Owner

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.