2.6.0-beta-4: Scoreboards crash

I'm not too sure about this one, and what makes it worse is that I'm working in Nim. So, a minimal reprodicible sample will be hard to come by. But the facts are thus:

  • code compiled on Mac M1 pdc 2.5.0
  • my code runs fine on Mac M1 sim 2.5.0
  • My code runs fine on revA 2.5.0
  • lua reference script runs fine on 2.6.0-beta4
  • Crashes on revA 2.6.0-beta4
  • code calls addScore (getPersonalBest similarly affected)
  • does not crash immediately, but a few seconds after addScore is called. Most probably when the server response is being processed.
--- crash at 2024/10/19 19:31:03---
build:be97134e-2.6.0-beta.4-buildbot
   r0:600144b1    r1:00000001     r2:00000000    r3: 0043f0e9
  r12:00000000    lr:0805393f     pc:08055cd4   psr: 210f0000
 cfsr:01000000  hfsr:40000000  mmfar:00000000  bfar: 00000000
rcccsr:00000000
heap allocated: 2167104
Lua totalbytes=0 GCdebt=0 GCestimate=0 stacksize=0

Feedback from Scratchminer

the only thing I can tell is that this is an unaligned access
[11:12 PM]
so somehow the processor is accessing a 16- or 32-bit value on an address that isn't aligned for that

In case it helps: very Work In Progress Nim code that produces the crash: [DRAFT] Scorbeoards by ninovanhooff · Pull Request #82 · samdze/playdate-nim · GitHub

Looking through the beta2 changelog (beta4 changelog not available to me) I see this scoreboard related change:

  • Fixed concurrency issue in C API scoreboard callbacks

I just played Gun Trails, which I'm pretty sure is a C-game using scoreboards. It crashes on 2.6.0-beta4 before reaching the start-screen, presumably because it pre-fetches the scoreboard.

I used the "gather diagnostics" and "send crash report" options. Panic-people may use the timestamp of this post to find it in their database.

@superfunc can you confirm? (also fyi)

Could it be that the typedef for the callbacks has changed? That would explain the crash, I think.

@dave. What can you tell us about this? If the api has changed, could I get a 2.6.0 build of the Mac sdk?

Hi Nino, please update your device to beta.5 and let me know if you can still repro this crash.

There is a marked improvement in beta 5:

  • Gun Trails doesn't crash anymore
  • addScore works OK
  • getPersonalBest works if a score has been set

But a crash remains:

  • When calling getPersonalBest with a boardId that exists but for which the user has not submitted (crash report sent through device just now)
--- crash at 2024/10/21 22:02:54---
build:a3328b3c-2.6.0-beta.5-buildbot
   r0:00000000    r1:00000000     r2:00000000    r3: 00000000
  r12:00000000    lr:08055cdb     pc:60015036   psr: 610f0000
 cfsr:00000082  hfsr:00000000  mmfar:00000008  bfar: 00000008
rcccsr:00000000
heap allocated: 1552672
Lua totalbytes=0 GCdebt=0 GCestimate=0 stacksize=0

I just saw that come in. Thanks so much for testing! :pray: I'll get that fixed this evening

1 Like

Probably not related, but on sim I might get this error message when calling getPersonalBest(): Player not registered

I assume this means I need to register my sim with my account. But when opening the Serial Number and Access Token window, The fields there match the info on my account (last sync date: today) and the window shows a green checkmark. In the settings > account I see my name and join date.

Is there anything I'm missing regarding this? Are there particular sim-only and device-only boards?

It looks like the crash is in your code, the $pc register is in the game code memory area. If you open the pdex.elf file in arm-none-eabi-gdb and do info line *0x15036 (game code is compiled to base address 0x0 then relocated to 0x60000000 on rev 1 hardware, 0x90000000 on rev 2) it should show you where it's happening. The cfsr register says that's an invalid access error, with the bad access happening at mmfar=0x8. One way that could happen is if you're trying to access the player field at offset 8 in the score you're getting back, but the score is NULL because you're getting an error instead.

Thanks for teaching me how to fish! I was able to find the function name where the crash happened, at least (line number doesn't make sense because the c code is generated from Nim source)

My assumption was that errorMessage and score are mutually exclusive, so I check the length of the message > 0 and then proceed to read the score.

In lua, the error message is "No personal best" in this case. Seems there is a discrepancy between lua and c. On the C-side, both score and errorMessage are nil.

I would suggest to copy the lua behavior and return an error message in this case. Alternatively: revise the scoreboard api docs, and explicitly mention that both error and score can be nil. There is also a mention of this score only being fetched from cache in lua while there isn't in the C. Which may or may not be correct if the behaviour differs.

Double-check: is it indeed the case that in C both error message and score are nil in this case? I couldn't attach a debugger on device, so I can only go by the fact that with this Nim code, the "Playdate-nim" error is indeed printed:

proc invokePersonalBestCallback(score: PDScorePtr, errorMessage: ConstChar) {.cdecl, raises: [].} =
  if errorMessage != nil:
    privatePersonalBestCallback(PDScore(), $errorMessage)
    return

  if score == nil:
    privatePersonalBestCallback(PDScore(), "Playdate-nim: No personal best")
    return

  [... proceed to read score ...]

Yep, you're right. It turns out that "No personal best" is created by the Lua wrapper when there's no score returned and there's no error. I'm torn: agree that it should be consistent, but I also don't think that should be reported as an error.

I think I'll leave it as is, where you get double NULL if there's no personal best, but I'll document it. The API is already public, and I hate changing API behavior if there's any chance people are already using it

3 Likes

Fine :slight_smile:

I will return an error on a double NULL from the playdate-nim api I am buliding though. I think it is the better behaviour also in line with http 404 which is an error code. It also fits our philosophy to provide an API that has native performance and the comfort / breadth of Lua. And I do have the luxury of no existing users ;-p

I'll prefix it with playdate-nim though so it's clear it is no sdk error