CCHttpClient crash issue (and fix)

in Cocos2d-x 2.13 and below there is an issue which can appear only on real iOS device (at least as it was for me)

it will appear only with second call to new CCHttpRequest, e. g.

CCHttpRequest * hr = new CCHttpRequest();
...
delete hr;

...

CCHttpRequest * hr2 = new CCHttpRequest();

    CCHttpRequest* request = new CCHttpRequest();
    request->setUrl(uri);
    request->setRequestType(CCHttpRequest::kHttpGet);
    request->setResponseCallback(this, callfuncND_selector(DataProvider::onHttpRequestCompleted));
    request->setTag(tag);
    CCHttpClient::getInstance()->send(request); // <-- it will crash here
    request->release();

...
delete hr2;

Reason of crash:

  • ‘need_quit’ flag is static variable and it will have TRUE value after first instance destruction;
  • bool CCHttpClient::lazyInitThreadSemphore() - first creates and detaches thread and only after that sets ‘need_quit’ to FALSE
  • on real device networkThread can check ‘need_quit’ flag FASTER than main thread will set it to FALSE
  • this causes newly created networkThread to stop immediately

Fix:

  • just move

    need_quit = false;

in

bool CCHttpClient::lazyInitThreadSemphore()
{
    if (s_requestQueue != NULL) {
        return true;
    } else {

        s_requestQueue = new CCArray();
        s_requestQueue->init();

        s_responseQueue = new CCArray();
        s_responseQueue->init();

        pthread_mutex_init(&s_requestQueueMutex, NULL);
        pthread_mutex_init(&s_responseQueueMutex, NULL);

        pthread_mutex_init(&s_SleepMutex, NULL);
        pthread_cond_init(&s_SleepCondition, NULL);

        pthread_create(&s_networkThread, NULL, networkThread, NULL);
        pthread_detach(s_networkThread);
        need_quit = false;

    }

    return true;
}

before

    pthread_create(&s_networkThread, NULL, networkThread, NULL);

Fixed function should look like that:

bool CCHttpClient::lazyInitThreadSemphore()
{
    if (s_requestQueue != NULL) {
        return true;
    } else {

        s_requestQueue = new CCArray();
        s_requestQueue->init();

        s_responseQueue = new CCArray();
        s_responseQueue->init();

        pthread_mutex_init(&s_requestQueueMutex, NULL);
        pthread_mutex_init(&s_responseQueueMutex, NULL);

        pthread_mutex_init(&s_SleepMutex, NULL);
        pthread_cond_init(&s_SleepCondition, NULL);

        need_quit = false;

        pthread_create(&s_networkThread, NULL, networkThread, NULL);
        pthread_detach(s_networkThread);

    }

    return true;
}

Sorry, I don’t have live own fork of cocos2d-x to make pull request on that.

good thank you….

Sergey Buravtsov wrote:

in Cocos2d-x 2.13 and below there is an issue which can appear only on real iOS device (at least as it was for me)
>
it will appear only with second call to new CCHttpRequest, e. g.
[…]
Reason of crash:
>

  • ‘need_quit’ flag is static variable and it will have TRUE value after first instance destruction;
  • bool CCHttpClient::lazyInitThreadSemphore() - first creates and detaches thread and only after that sets ‘need_quit’ to FALSE
  • on real device networkThread can check ‘need_quit’ flag FASTER than main thread will set it to FALSE
  • this causes newly created networkThread to stop immediately
    >
    Fix:
    >
  • just move
    […]
    in
    […]
    >
    before
    […]
    >
    Fixed function should look like that:
    […]
    >
    Sorry, I don’t have live own fork of cocos2d-x to make pull request on that.