Websocket crash. Creator 1.6.1 release

频率:偶现
平台:ios
Creator版本:1.6.1 release
手机:苹果5S
系统版本:10.3.2 (14F89)

这个问题我自己已经解决了,引擎组的可以看一下,我就不说怎么改了,免得别人说你显摆技术.

可以的话,说下拿块有问题吧,:smile:,好自己先改着

jsb_websocket.cpp

这个文件自己查一下代码,把executeFunctionWithOwner之前都判断一下参数是否合法,另外static_cast后先判断指针是否为空,不为空再使用.还有应该可以直接改executeFunctionWithOwner里面,在使用前都先判断第一个参数是否合法.

bool ScriptingCore::executeFunctionWithOwner(JS::HandleValue owner, const char name, const JS::HandleValueArray& args, JS::MutableHandleValue retVal)
{
bool bRet = false;
bool hasFunc;
JSContext
cx = this->_cx;
JS::RootedValue funcVal(cx);
JS::RootedValue ownerval(cx, owner);
JS::RootedObject obj(cx);
if (ownerval.isObject())
obj = ownerval.toObjectOrNull();

do
{
    if (JS_HasProperty(cx, obj, name, &hasFunc) && hasFunc) {
        if (!JS_GetProperty(cx, obj, name, &funcVal)) {
            break;
        }
        if (funcVal.isNullOrUndefined()) {
            break;
        }

        bRet = JS_CallFunctionValue(cx, obj, funcVal, args, retVal);
        if (JS_IsExceptionPending(cx)) {
            handlePendingException(cx);
        }
    }
}while(0);
return bRet;

}

稍改一下这个应该是可以的,好像里面有些小手误.

void js_cocos2dx_WebSocket_finalize(JSFreeOp *fop, JSObject *obj) {
CCLOG(“jsbindings: finalizing JS object %p (WebSocket)”, obj);
WebSocket *cobj = static_cast<WebSocket *>(JS_GetPrivate(obj));
if (cobj)
{
js_proxy_t * p = jsb_get_native_proxy(cobj);
#if not CC_ENABLE_GC_FOR_NATIVE_OBJECTS
auto copy = &p->obj;
JS::RemoveObjectRoot(cx, copy);
#endif
jsb_remove_proxy§;

    ScriptingCore::getInstance()->setFinalizing(true);
    // Manually close if WebSocket is not closed
    if (cobj->getReadyState() != WebSocket::State::CLOSED)
    {
        cobj->closeAsync();
    }
    static_cast<JSB_WebSocketDelegate*>(cobj->getDelegate())->release();
    cobj->release();
    ScriptingCore::getInstance()->setFinalizing(false);
}

}

还有jsb_get_native_proxy,这里可能返回了空指针或野指针.因为宕机出现在这个文件,我只是顺手把所有保护都加上,引起这个宕机最关键的代码应该是这里.

另外,旁观者不要再误读,我这里只是为了解决问题,另外是有人刚好问了,所以才说出解决方案.也没有所谓几层意思.:sweat_smile:真是怕了,唉.每次发贴都要解释再三.

请问

android上没问题吗?

这个bug ,如何触发?

目前我这个来自第三方上报,我改后,暂时没有再发现,安卓暂时也没有发现有这个.是偶现的,不过我猜跟销毁流程有关,不过这个当时并没有发生在退出app时.

ios 上周期性的出现 Websocket Failed With Error Error Domain=NSPOSIXErrorDomain Code=57 “Socket is not connected”
cc v.1.6.1-beta.2

lz 有遇到过没?@mm

暂时没有呢,你自己有没有加入心跳机制.最好自己加上心跳检测机制.不过目前看你这个应该不是这些引起的.

记下留备,感谢分享!:)

谢谢反馈

finalize 中缺失的空指针校验是之前已经修复了,可能你们没有拉取最新的 1.6 分支

https://github.com/cocos-creator/cocos2d-x-lite/pull/770/files#diff-ae4c964edaa776da9c6ee6a3f93e7bccR217

建议上面 PR 中其他相关的修改也一并合并一下比较好

关于 executeFunctionWithOwner 的问题,也按照你的建议加强了一下

https://github.com/cocos-creator/cocos2d-x-lite/pull/798

1赞

收到,辛苦了.

void PoolManager::destroyInstance()
{
delete s_singleInstance;
s_singleInstance = nullptr;
}
这个写得也有点小问题,刚在查另一个退出宕机问题,暂时是把这个delete s_singleInstance;给注释了.

除了上面那个,我们之前还改了这个,避免退出宕机,其实退出的时候宕机对用户没什么影响,但反映在苹果的统计后台,很碍眼.
void ScriptEngineManager::destroyInstance()
{
/if (s_pSharedScriptEngineManager)
{
delete s_pSharedScriptEngineManager;
s_pSharedScriptEngineManager = nullptr;
}
/
}

PoolManager 的实现没问题,如果不 delete 是有泄漏的,根本原因不在这里,可能 Texture2D 的引用出现了问题,这个就要具体重现后分析了。

ScriptEngineManager 也是一样的道理

退出时的崩溃问题我们在 1.6 之后基本都修复了,至少我们的测试中没有重现过类似的问题了,我感觉你们的一些用法还是我们没有覆盖到,很难说是什么问题

好的,我们也查了,发现这里本身的写法有点点小瑕疵,但都不会引起宕机,可能是其它原因,但目前避免宕机最有效的方式还是注释这些destroyInstance();

附小瑕疵:
void PoolManager::destroyInstance()
{
delete s_singleInstance;
s_singleInstance = nullptr;
}
应该写为:

void PoolManager::destroyInstance()
{
if(s_singleInstance != nullptr)
{
delete s_singleInstance;
s_singleInstance = nullptr;
}
}

嗯是的,这样写更安全。
不过如果真出现PoolManager::destroyInstance两次被调用,也得查查为什么地方引起的。