Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Unity-v2] Bug: Check failed: Handle not reset in first callback. See comments on |v8::WeakCallbackInfo|.. #1203

Closed
3 tasks done
chexiongsheng opened this issue Feb 13, 2023 · 2 comments
Assignees
Labels
bug Something isn't working Unity

Comments

@chexiongsheng
Copy link
Collaborator

前置阅读 | Pre-reading

Puer的版本 | Puer Version

v2.0.0

Unity的版本 | Unity Version

all

发生在哪个平台 | Platform

All

错误信息 | Error Message

Check failed: Handle not reset in first callback. See comments on |v8::WeakCallbackInfo|..

问题重现 | Bug reproduce

脚本1

using System;
using DefaultNamespace;
using UnityEngine;
using UnityEngine.SceneManagement;

public class Scene1Script : MonoBehaviour
{
    public Vector3[] TestArray = {new (0, 0, 0), new (0, 0, 0) };

    private Action<Scene1Script> callback;

    public void gotoScene2()
    {
        SceneManager.LoadSceneAsync("Scene2");
    }
    void Start()
    {
        callback = JsEngine.Vm.Eval<Action<Scene1Script>>(@"(function(mono) {
            const len = mono.TestArray.Length;
            for (let j = 0; j < 40000; ++j) {
            for (let i = 0; i < len; ++i) {
                const vec = mono.TestArray.get_Item(i);
            }
            }
        })");
    }

    // Update is called once per frame
    void Update()
    {
        callback(this);
    }
}

脚本2

using System;
using DefaultNamespace;
using UnityEngine;
using UnityEngine.SceneManagement;

public class Scene2Script : MonoBehaviour
{
    private Action callback;

    public void goBack()
    {
        SceneManager.LoadScene("Scene1");
    }
    void Start()
    {
        callback = JsEngine.Vm.Eval<Action>(@"(function() {
            let List = puer.$generic(
            CS.System.Collections.Generic.List$1,
            CS.System.Int32 // CS.UnityEngine.Vector3
            );
            for (let i = 0; i < 10000; ++i) {
                let lst = new List();
            }
        })");
    }

    // Update is called once per frame
    void Update()
    {
        callback();
    }
}

场景1加载脚本1,场景2加载脚本2

游戏启动后加载场景1.。
一会儿后点击切场景,闪退,日志报:Check failed: Handle not reset in first callback. See comments on |v8::WeakCallbackInfo|..

CrashRepro.zip

@chexiongsheng chexiongsheng added bug Something isn't working Unity labels Feb 13, 2023
@chexiongsheng
Copy link
Collaborator Author

chexiongsheng commented Feb 13, 2023

原因分析:

1、脚本1将产生指针类型的,指向TestArray里头字段js对象。
2、切换场景,Scene1Script 对象被gc,TestArray也被gc,但js中1的指针类型对象还没gc。
3、脚本2会在js里new对象,该对象重用了TestArray的内存。而在CppObjectMapper.cpp的BindCppObject中认为如果PassByPointer为false(在js中new会如此),这是新分配的内存,认为肯定不会和之前的重复,因而直接覆盖了CDataCache之前指针类型对象,导致之前指针类型对象释放的时候没调用到Globa.Reset(因为之前的Globa.Reset已经被冲掉),进而触发v8的assert。

chexiongsheng added a commit that referenced this issue Feb 13, 2023
@chexiongsheng
Copy link
Collaborator Author

附上简化版的用例(仅一个脚本即可)

using UnityEngine;
using Puerts;
using System;

public class TestEvent
{
    public Vector3[] testArray = { new Vector3(0, 0, 0), new Vector3(0, 0, 0) };
}

public class Test2 : MonoBehaviour
{
    private JsEnv jsEnv;
    // Start is called before the first frame update
    void Start()
    {
        jsEnv = new JsEnv();
        jsEnv.Eval(@"
let o = new CS.TestEvent();

const len = o.testArray.Length;
let cached = [];
for (let j = 0; j < 40000; ++j) {
for(let i = 0; i < len; ++i) {
    cached.push(o.testArray.get_Item(i));
}
}
o = undefined;
let List = puer.$generic(CS.System.Collections.Generic.List$1,
    CS.System.Int32
);
");
        jsEnv.Eval("gc()");
        
        GC.Collect();
        GC.WaitForPendingFinalizers();
        //jsEnv.Dispose();
        UnityEngine.Debug.Log("-------------Start---------------");
    }

    // Update is called once per frame
    void Update()
    {
        UnityEngine.Debug.Log("--------------Update--------------");
        jsEnv.Eval(@"
cached = undefined;
for (let k = 0; k < 10000; ++k) {
    let lst = new List();
}

");
    }
}

感觉要触发也比较苛刻
1、我把Start的40000次循环去掉,就重现不了了
2、好几次Update后才可以触发

Tangxinwei added a commit to Tangxinwei/puerts that referenced this issue Feb 14, 2023
chexiongsheng pushed a commit that referenced this issue Feb 14, 2023
zombieyang pushed a commit to zombieyang/puerts that referenced this issue Feb 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Unity
Projects
None yet
Development

No branches or pull requests

2 participants