Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

All calls erroring out #88

Closed
PureForm opened this Issue · 12 comments

4 participants

@PureForm

I just updated our files with the current source and immediately ran into issues. All calls to twitter-async break, and I think the culprit may be in EpiCurl::getKey().

Here is the stack trace: [I omitted any sensitive data]
WARNING: curl_getinfo(): supplied argument is not a valid cURL handle resource in Epi/EpiCurl.php on line 169
# 0 curl_getinfo(, 1048577) called at [Epi/EpiCurl.php:169]

# 1 EpiCurl->stopTimer(, Resource id # 27) called at [Epi/EpiCurl.php:146]

# 2 EpiCurl->storeResponse(Resource id # 27) called at [Epi/EpiCurl.php:131]

# 3 EpiCurl->headerCallback(Resource id # 27, HTTP/1.1 200 OK

)

# 4 curl_exec(Resource id # 27) called at [Epi/EpiCurl.php:150]

# 5 EpiCurl->storeResponse(Array ([handle] => Resource id # 27), ) called at [Epi/EpiCurl.php:41]

# 6 EpiCurl->addEasyCurl(Resource id # 27) called at [Epi/EpiOAuth.php:202]

# 7 EpiOAuth->executeCurl(Resource id # 27) called at [Epi/EpiOAuth.php:228]

# 8 EpiOAuth->httpGet(http://api.twitter.com/1/users/show.json, Array ([request] => Array ([user_id] => 17909625),[oauth] => Array ([oauth_consumer_key] => OMITTED,[oauth_token] => OMITTED,[oauth_nonce] => OMITTED,[oauth_timestamp] => OMITTED,[oauth_signature_method] => HMAC-SHA1,[oauth_version] => 1.0,[oauth_signature] => OMITTED))) called at [Epi/EpiOAuth.php:82]

# 9 EpiOAuth->httpRequest(GET, http://api.twitter.com/1/users/show.json, Array ([user_id] => 17909625), )

# 10 call_user_func(Array ([0] => EpiTwitter Object ([] => http://twitter.com/oauth/request_token,[] => http://twitter.com/oauth/access_token,[] => http://twitter.com/oauth/authorize,[] => http://twitter.com/oauth/authenticate,[] => http://twitter.com,[] => http://api.twitter.com,[] => http://search.twitter.com,[] => EpiTwitter (http://github.com/jmathai/twitter-async/tree/),[] => 1,[] => ,[version] => 1.0,[] => OMITTED,[] => OMITTED,[] => OMITTED,[] => OMITTED,[] => HMAC-SHA1,[] => ,[] => ,[] => Array ([0] => Expect:,[1] => Authorization: OAuth realm="http://api.twitter.com/1/users/show.json",oauth_consumer_key="OMITTED",oauth_token="OMITTED",oauth_nonce="OMITTED",oauth_timestamp="OMITTED",oauth_signature_method="HMAC-SHA1",oauth_version="1.0",oauth_signature="OMITTED",[2] => User-Agent: EpiTwitter (http://github.com/jmathai/twitter-async/tree/)),[] => 5,[] => 5,[curl] => EpiCurl Object ([] => Resource id # 26,[] => ,[] => ,[] => ,[] => ,[] => 1.1,[] => Array ([Resource id # 27] => Resource id # 27),[] => Array (),[] => Array ([code] => 2097154,[time] => 3145731,[length] => 3145743,[type] => 1048594,[url] => 1048577))),[1] => httpRequest), GET, http://api.twitter.com/1/users/show.json, Array ([user_id] => 17909625), ) called at [Epi/EpiTwitter.php:117]

# 11 EpiTwitter->request(GET, /users/show.json, Array ([user_id] => 17909625)) called at [Epi/EpiTwitter.php:36]

# 12 EpiTwitter->get(/users/show.json, Array ([user_id] => 17909625)) called at [file.inc:84]

@anuj138

I think these errors due to asynchronous calls. Please try for synchronous calls.

http://github.com/jmathai/twitter-async/issues#issue/49/comment/415443

Thanks,
Anuj

@jmathai
Owner

Anuj,

If you change line 145 in EpiCurl from:
$key = $this->getKey($ch['handle']);

to:
$key = (string)$done['handle'];

Does that solve the problem?

@GLStephen

Just slightly different errors:

PHP Notice: Undefined variable: done in N:\DEV\STEPHEN\includes\twitter\epitwitter\EpiCurl.php on line 145
PHP Notice: Undefined variable: done in N:\DEV\STEPHEN\includes\twitter\epitwitter\EpiCurl.php on line 145
PHP Warning: curl_getinfo() expects parameter 1 to be resource, null given in N:\DEV\STEPHEN\includes\twitter\epitwitter\EpiCurl.php on line 169
PHP Warning: curl_getinfo() expects parameter 1 to be resource, null given in N:\DEV\STEPHEN\includes\twitter\epitwitter\EpiCurl.php on line 170
PHP Warning: curl_getinfo() expects parameter 1 to be resource, null given in N:\DEV\STEPHEN\includes\twitter\epitwitter\EpiCurl.php on line 171
PHP Warning: curl_multi_getcontent() expects parameter 1 to be resource, null given in N:\DEV\STEPHEN\includes\twitter\epitwitter\EpiCurl.php on line 148

@anuj138

Hi GLStephen,

Please paste your EpiCurl.php file. So I can check it foor the errors.

Thanks,
Anuj

@GLStephen

<?php
class EpiCurl
{
const timeout = 3;
static $inst = null;
static $singleton = 0;
private $mc;
private $msgs;
private $running;
private $execStatus;
private $selectStatus;
private $sleepIncrement = 1.1;
private $requests = array();
private $responses = array();
private $properties = array();
private static $timers = array();

function __construct()
{
if(self::$singleton == 0)
{
throw new Exception('This class cannot be instantiated by the new keyword. You must instantiate it using: $obj = EpiCurl::getInstance();');
}

$this->mc = curl_multi_init();
$this->properties = array(
  'code'  => CURLINFO_HTTP_CODE,
  'time'  => CURLINFO_TOTAL_TIME,
  'length'=> CURLINFO_CONTENT_LENGTH_DOWNLOAD,
  'type'  => CURLINFO_CONTENT_TYPE,
  'url'   => CURLINFO_EFFECTIVE_URL
  );

}

public function addEasyCurl($ch)
{
$key = $this->getKey($ch);
$this->requests[$key] = $ch;
curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, 'headerCallback'));
$done = array('handle' => $ch);
$this->storeResponse($done, false);
$this->startTimer($key);
return new EpiCurlManager($key);
}

public function addCurl($ch)
{
$key = $this->getKey($ch);
$this->requests[$key] = $ch;
curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, 'headerCallback'));

$code = curl_multi_add_handle($this->mc, $ch);
$this->startTimer($key);

// (1)
if($code === CURLM_OK || $code === CURLM_CALL_MULTI_PERFORM)
{
  do {
      $code = $this->execStatus = curl_multi_exec($this->mc, $this->running);
  } while ($this->execStatus === CURLM_CALL_MULTI_PERFORM);

  return new EpiCurlManager($key);
}
else
{
  return $code;
}

}

public function getResult($key = null)
{
if($key != null)
{
if(isset($this->responses[$key]))
{
return $this->responses[$key];
}

  $innerSleepInt = $outerSleepInt = 1;
  while($this->running && ($this->execStatus == CURLM_OK || $this->execStatus == CURLM_CALL_MULTI_PERFORM))
  {
    usleep($outerSleepInt);
    $outerSleepInt = intval(max(1, ($outerSleepInt*$this->sleepIncrement)));
    $ms=curl_multi_select($this->mc, 0);
    if($ms > 0)
    {
      do{
        $this->execStatus = curl_multi_exec($this->mc, $this->running);
        usleep($innerSleepInt);
        $innerSleepInt = intval(max(1, ($innerSleepInt*$this->sleepIncrement)));
      }while($this->execStatus==CURLM_CALL_MULTI_PERFORM);
      $innerSleepInt = 1;
    }
    $this->storeResponses();
    if(isset($this->responses[$key]['data']))
    {
      return $this->responses[$key];
    }
    $runningCurrent = $this->running;
  }
  return null;
}
return false;

}

public static function getSequence()
{
return new EpiSequence(self::$timers);
}

public static function getTimers()
{
return self::$timers;
}

private function getKey($ch)
{
return (string)$ch;
}

private function headerCallback($ch, $header)
{
$_header = trim($header);
$colonPos= strpos($_header, ':');
if($colonPos > 0)
{
$key = substr($_header, 0, $colonPos);
$val = preg_replace('/^\W+/','',substr($_header, $colonPos));
$this->responses[$this->getKey($ch)]['headers'][$key] = $val;
}
$this->storeResponse($ch);
return strlen($header);
}

private function storeResponses()
{
while($done = curl_multi_info_read($this->mc))
{
$this->storeResponse($done);
}
}

private function storeResponse($ch, $isAsynchronous = true)
{
$key = $this->getKey($ch['handle']);
$this->stopTimer($key, $ch);
if($isAsynchronous)
$this->responses[$key]['data'] = curl_multi_getcontent($ch['handle']);
else
$this->responses[$key]['data'] = curl_exec($ch['handle']);

foreach($this->properties as $name => $const)
{
  $this->responses[$key][$name] = curl_getinfo($ch['handle'], $const);
}
if($isAsynchronous)
  curl_multi_remove_handle($this->mc, $ch['handle']);
curl_close($ch['handle']);

}

private function startTimer($key)
{
self::$timers[$key]['start'] = microtime(true);
}

private function stopTimer($key, $done)
{
self::$timers[$key]['end'] = microtime(true);
self::$timers[$key]['api'] = curl_getinfo($done['handle'], CURLINFO_EFFECTIVE_URL);
self::$timers[$key]['time'] = curl_getinfo($done['handle'], CURLINFO_TOTAL_TIME);
self::$timers[$key]['code'] = curl_getinfo($done['handle'], CURLINFO_HTTP_CODE);
}

static function getInstance()
{
if(self::$inst == null)
{
self::$singleton = 1;
self::$inst = new EpiCurl();
}

return self::$inst;

}
}

class EpiCurlManager
{
private $key;
private $epiCurl;

public function __construct($key)
{
$this->key = $key;
$this->epiCurl = EpiCurl::getInstance();
}

public function __get($name)
{
$responses = $this->epiCurl->getResult($this->key);
return isset($responses[$name]) ? $responses[$name] : null;
}

public function __isset($name)
{
$val = self::__get($name);
return empty($val);
}
}

/*

  • Credits:
  • - (1) Alistair pointed out that curl_multi_add_handle can return CURLM_CALL_MULTI_PERFORM on success. */
@anuj138

Hi GLStephen,

You don't need to call any of getResult, getKey, storeResponses and storeResponse functions once you have changed your code for synchronous mode.

http://github.com/jmathai/twitter-async/issues#issue/49/comment/415443

if you want to get headers and body part from curl response:

For synchronous mode, change following line in EpiOAuth.php (3 times)

$resp = $this->curl->addCurl($ch); to
$resp = curl_exec($ch);

if you want to get headers and body part from curl:
$info = curl_getinfo($ch);
$header = substr($resp, 0, $info['header_size']);
$body = substr($resp, -$info['download_content_length']);

$body will give you response body while $header will give you header part of response.

@GLStephen

I'm not calling any of those. I'm using the stock code downloaded from here for Twitter-Async. The calls I'm making are all into the Twitter object. This is with a completely stock install and code that runs perfectly fine in 5.2.10. That code doesn't work in 5.3.3 though (on Windows). Load the current version of Twitter-Async and I start getting these errors. I'm not calling the getResult, getKey and storeResponse methods.

@GLStephen

Just to clarify, here is how I am calling these:

$twitterObj = new EpiTwitter(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET);

$twitterObj->setToken($user_oauth_token, $twitter_oauth_token_secret);

$twitterInfo= $twitterObj->get_accountVerify_credentials();

$twitterInfo->response;

The $twitterInfo= $twitterObj->get_accountVerify_credentials(); line generates these errors.

@jmathai
Owner

Removing store response call from callback function.
Closed by b468694

@jmathai
Owner

Please update and verify if the problems go away.

@GLStephen

Works perfectly! Thanks for the assistance. This should clear our last hurdle to PHP 5.3.3 support in our application.

@PureForm

That seems to have done it :-)

Thank you!

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.