Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Crashes in Background Thread — Gideros Forum

Crashes in Background Thread

troysandaltroysandal Member
edited February 8 in General questions
Gideros - 2025.3
Machine - M1 Max Macbook Pro
OS : macOS Sequoia 15.7.3

I’m experiencing a crash on application startup and need some help. Here’s what’s happening. During startup my application is making a lot of nested calls to both Parse backend and various AppKit APIs, all through a Wax bridge. In my crash scenario I’ve called PFGeoPoint:geoPointForCurrentLocationInBackground() with a Lua callback function. As Lua is preparing to call the callback, I get a crash. Sometimes in the main thread (Thread 1) but sometimes in Thread 21. The stack traces always vary but what they all have in common is that Thread 21 is also executing Lua code called from Gideros LuaApplication::broadcastEvent. Both threads are using the same lua_State* L pointer.

Pictures of the stack traces are below. I have 2 ideas currently. First, this is a problem I introduced with my changes to BhWax. Second, we have 2 native threads modifying the same lua_State pointer and crashing. I am leaning towards the second idea because as far as I can tell, Lua states are NOT thread safe.

If anyone has any ideas I would love to hear it. Thanks in advance.
Thread 1
0 luau_execute
1 luau_execute
2 luaD_call
3 ::lua_call(lua_State *, int, int)
4 eventClosureWithData 5 luau_precall
6 luaD_call
7 ::lua_call(lua_State *, int, int)
8 CppLuaBridge::luaEvent
9 EventDispatcher::dispatchEvent
10 EventDispatcherBinder::dispatchEvent
11 luau_execute
12 luau_execute
13 luaD_call
14 ::lua_call(lua_State *, int, int)
15 luaBlockARM64ReturnBufferWithParameters
16 __lua_LongLong_block_1q block_inv...
17 [PFGeoPoint geoPointForCurrentLocationWithError:]
18 -[PFLocationManager locationManag...
19 __lldb_unnamed_symbol1491
29 UIApplicationMain
30 main
31 start_sim
32 start
Thread 21
0 ::lua_remove(lua_State *, int)
1 ::lua_pcall_traceback(lua_State *, int, ...
2 LuaApplication::broadcastEvent(event, status)
3 ApplicationManager::surfaceChanged
4 -[EAGLView createFramebuffer]
5 -[EAGLView setFramebuffer]
6 ApplicationManager::renderLoop
7 ApplicationManager:renderLoop_s
8 __NSThread__start_)
10 thread_start

Likes: MoKaLux

+1 -1 (+1 / -0 )Share on Facebook

Comments

  • hgy29hgy29 Maintainer
    Hi troysandal,
    I think you are right and the crash must arise because of concurrent call to the same lua_State from two threads. On iOS, the lua thread is the render thread (thread 21 or 22 in your tests), so the offending lua call is the one from thread 1.
    I am not aware of how BhWax internally works, but the result of your background task should be sent back to lua from the render thread. Within gideros code this is done by posting an event to the render thread (https://github.com/gideros/gideros/blob/master/libgid/src/gevent.cpp#L244)

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • Thank you for the response, this helps. I'll look at using gevent_EnqueueEvent inside BhWax

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • hgy29hgy29 Maintainer
    If you go tha way, here are few things to know:
    - the g_id parameter acts like an event category. You should get one with g_NextId() at initialization and reuse it for all enqueue event calls. (https://github.com/gideros/gideros/blob/master/libgid/include/gglobal.h#L16)
    - the type parameter is whatever you like, it only has a meaning in the context of your callback.
    - the event parameter is a pointer to whatever data you need to pass alongside the event. If you allocated it before enqueueing it, you can set the 'free' parameter to true to have Gideros deallocate it when processed.
    - the udata parameter can be used as a context pointer. If your call back depends on a C++ object, this would be the instance pointer.
    - In your callback, you'll probably need the main lua_State pointer. Don't save the L argument from a random lua binder function, as it can represent a coroutine or a different lua thread. Instead save the lua_State given in g_initializePlugin(), this one is guaranteed to be the main lua state.

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
Sign In or Register to comment.