HaxeFoundation / HaxeFoundation/hxcpp

Crash because hxcpp's GC fail to mark a local variable

Open
#760 11 comments 1 reaction 0 assignees View on GitHub
Dominant language
C++
Stars
330
Forks
227
Avg merge
2d 16h
Merged PRs (30d)
18

Description

I have a crash, which is very easy to reproduce。
Finally, I found the root cause of crash! That is the hxcpp's GC fail to mark a local variable,It's amazing!

########################################################################
> **How to reproduce:**

1. In order to simplify the analysis, let's modify the openfl-sample BunnyMark's "_**Main.hx**_":

```
for (i in 0...1) { // Modify from 100 to 1
addBunny ();
}
```

2. Build the openfl-sample BunnyMark :
```
openfl build wasm.
```
Then you can open the html page "index.html" which generated by lime. You'll find that everything is OK, nothing error.

3. Modify lime's _**EmscriptenPlatform.hx**_:

```
if (!project.defines.exists ("openfl_skip_haxe_build")) { //Add
ProcessHelper.runCommand ("", "haxe", args);
} //Add
```

This will help us to modify and build those cpp files generated by Haxe.

4. Modify BunnyMark's _**Bunny.cpp**_ file:

```
void Bunny_obj::__construct(){
HX_STACKFRAME(&_hx_pos_7e22fcda50e23ba6_16_new)
HXDLIN( 16) super::__construct(0,null(),null(),null(),null(),null(),null(),null());
__hxcpp_collect(); // Add this line
}
```

The above modification is to force GC (mark-sweep).

5. Build again the openfl sample project by:
```
openfl build wasm -Dopenfl_skip_haxe_build
```
Then open the BunnyMark's index.html on the browser, Crash will occur !

########################################################################
> **Crash Analysis:**

1. Let's print the gc log in the _**immix.cpp**_:

```
void MarkConservative(int *inBottom, int *inTop,hx::MarkContext *__inCtx)
{
.......
if ( t==allocObject )
{
GCLOG(" Mark object %p (%p)\n", vptr,ptr); // print gc log
HX_MARK_OBJECT( ((hx::Object *)vptr) );
lastPin = vptr;
info->pin();
}
......
}
```

2. Print the memory address of the local variable which gc-mark is missed.
This local variable is Bunny_obj.
Modify the _**Main.cpp**_ of BunnyMark:
>
> void Main_obj::addBunny(){
> HX_GC_STACKFRAME(&_hx_pos_e47a9afac0942eb9_64_addBunny)
> HXLINE( 66) Bunny bunny = Bunny_obj::__alloc( HX_CTX );
> printf("Main_obj::addBunny() bunny->Ptr: %p\n", bunny.GetPtr()); //Add this line
> HXLINE( 67) bunny->set_x(( (Float)(0) ));
> HXLINE( 68) bunny->set_y(( (Float)(0) ));
> HXLINE( 69) bunny->speedX = (::Math_obj::random() * 5);
> HXLINE( 70) bunny->speedY = ((::Math_obj::random() * 5) - ((Float)2.5));
> HXLINE( 71) this->bunnies->push(bunny);
> HXLINE( 72) this->tilemap->addTile(bunny);
> }

Important: Do not print Bunny_obj* in Bunny_obj::__alloc()

3. Comare the gc log of the normal version and the gc log of the crash version.
compile Bunny.cpp with emcc -O0: (no crash)
http://kuangyaozong.com/wasm-bunny_cpp-O0/
compile Bunny.cpp with emcc -O1: (crash)
http://kuangyaozong.com/wasm-bunny_cpp-O1/

4. The important local variable:

Bunny.cpp:
```
hx::ObjectPtr Bunny_obj::__alloc(hx::Ctx *_hx_ctx) {
Bunny_obj *__this = (Bunny_obj*)(hx::Ctx::alloc(_hx_ctx, sizeof(Bunny_obj), true, "Bunny"));
*(void **)__this = Bunny_obj::_hx_vtable;
__this->__construct();
return __this;
}
```

The local variable is __this in Bunny_obj::__alloc().

I found that the Bunny_obj* is missing in GC-Mark, then the Bunny_obj* is collected by GC , so crash happened。

This local variable is as the memory address of the Bunny_obj object in function Bunny_obj::__alloc() . In fact, the value of this local variable will return and becomes a member of an Object, it should not be collected by GC !

5. Compile Bunny.cpp Using emcc -O0, instead of emcc -O1.
Open **_emscripten-toolchain.xml_**, modify like this:
```




```
Then build BunnyMark with:
`
openfl build wasm -Dopenfl_skip_haxe_build
`
Finally, run the html file, crash disappeared,no error. So compiling with "emcc -O0" may be a solution of this crash.

########################################################################
> **Conclusion:**

The MARK process of hxcpp GC miss Mark for some local variable when compile emscripten target with emcc -O1.

Can anyone help me ? What is the reason?

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.