ExOK / Celeste64

A game made by the Celeste developers in a week(ish, closer to 2)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

M1 Mac: Apparent segfault (exit code 139)

jneen opened this issue · comments

To reproduce:

[0: jneen@lavender tmp ] $ 
; uname -a
Darwin lavender.[REDACTED] 23.3.0 Darwin Kernel Version 23.3.0: Wed Dec 20 21:30:44 PST 2023; root:xnu-10002.81.5~7/RELEASE_ARM64_T6000 arm64

[0: jneen@lavender tmp ] $ 
; dotnet --version
8.0.101

[0: jneen@lavender tmp ] $ 
; git clone https://github.com/ExOK/Celeste64
Cloning into 'Celeste64'...
remote: Enumerating objects: 422, done.
remote: Counting objects: 100% (21/21), done.
remote: Compressing objects: 100% (18/18), done.
remote: Total 422 (delta 3), reused 9 (delta 3), pack-reused 401
Receiving objects: 100% (422/422), 25.20 MiB | 23.06 MiB/s, done.
Resolving deltas: 100% (70/70), done.

[0: jneen@lavender tmp ] $ 
; cd Celeste64/

[0: jneen@lavender Celeste64 ] -> main $ 
; git rev-parse HEAD
52240c15f035c66e7131161f97fa003e696aa7ee

[0: jneen@lavender Celeste64 ] -> main $ 
; dotnet restore
  Determining projects to restore...
  Restored /private/tmp/Celeste64/Celeste64.csproj (in 165 ms).

[0: jneen@lavender Celeste64 ] -> main $ 
; dotnet run
Celeste 64 v.1.0.1
Foster: v0.1.14
Platform: Darwin 23.3.0 Darwin Kernel Version 23.3.0: Wed Dec 20 21:30:44 PST 2023; root:xnu-10002.81.5~7/RELEASE_ARM64_T6000 (Arm64)
Framework: .NET 8.0.1
SDL: v2.28.5
OpenGL: v4.1 Metal - 88, Apple M1 Max
FMOD Bindings: v20218
FMOD: v20218
Loaded Bank: /private/tmp/Celeste64/bin/Debug/net8.0/../../../Content/Audio/Master.strings.bank
Loaded Bank: /private/tmp/Celeste64/bin/Debug/net8.0/../../../Content/Audio/Master.bank
Loaded Bank: /private/tmp/Celeste64/bin/Debug/net8.0/../../../Content/Audio/sfx.bank
Loaded Bank: /private/tmp/Celeste64/bin/Debug/net8.0/../../../Content/Audio/music.bank
WARNING: Output of vertex shader 'v_col' not read by fragment shader
WARNING: Output of vertex shader 'v_type' not read by fragment shader

WARNING: Output of vertex shader 'v_color' not read by fragment shader

Loaded Assets in 451ms

[139: jneen@lavender Celeste64 ] -> main $ 
; echo $?
139

What I observe when I run the game with dotnet run is that the game opens, transitions to full screen, and then immediately closes. Every once in a while I've been able to get it to load the opening animation, but then it immediately closes again.

My partner has tested on her Intel mac and it seems to work okay.

Thank you so much for this game, I'm super hyped to play it. I hope this report is helpful, and I'm happy to test anything you like.

Cheers!
jneen

I feel like this must be in Foster's opengl rendering code somewhere. Will try to debug this but I don't have an M1 mac super accessible right now, so it may take a bit.

Sure thing no worries. If there's debug flags I could compile with to get a more detailed output I'm happy to look or step through somehow.

I am able to run after multiple attempts. The game crashes on the first restore though. One possible difference is that I have Metal-86.

There is no crash with dotnet restore --no-dependencies, so it's likely that the problem is in Foster.

I've updated on git to 0aea6cb, and now it looks like I can't build it at all on account of it's expecting x64 for some reason.

[0: jneen@lavender Celeste64 ] -> main $ 
; dotnet build
MSBuild version 17.8.3+195e7f5a3 for .NET
  Determining projects to restore...
  Restored /Users/jneen/src/Celeste64/Celeste64.csproj (in 155 ms).
/opt/homebrew/Cellar/dotnet/8.0.1/libexec/sdk/8.0.101/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.RuntimeIdentifierInference.targets(288,5): error NETSDK1032: The RuntimeIdenti
fier platform 'osx-arm64' and the PlatformTarget 'x64' must be compatible. [/Users/jneen/src/Celeste64/Celeste64.csproj]

Build FAILED.

/opt/homebrew/Cellar/dotnet/8.0.1/libexec/sdk/8.0.101/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.RuntimeIdentifierInference.targets(288,5): error NETSDK1032: The RuntimeIdenti
fier platform 'osx-arm64' and the PlatformTarget 'x64' must be compatible. [/Users/jneen/src/Celeste64/Celeste64.csproj]
    0 Warning(s)
    1 Error(s)

Time Elapsed 00:00:00.55

Update: I can get it to build with -c Release but I think the fmod libs aren't being copied over. After copying them over, manually* it will run and then immediately segfault again, so we're back to square one.

*(cp Source/Audio/FMOD/libs/osx/libfmod*.dylib bin/Release/net8.0/osx-arm64/)

I think this line would need to be amended to include osx-arm64:
https://github.com/ExOK/Celeste64/blob/main/Celeste64.csproj#L30

and then the build action likely needs updating to also include osx-arm versions, right now it's only doing x64 as far as I know.

All that said if you're still getting segfaults on latest when you build it yourself, something must still be broken despite recent fixes in Foster ... hmm.

Tried on a fresh clone as well, here's the log in case that's helpful.

raw-build.log

For those that are still running into crashes, what worked for me was following a comment from another issue in this repo:

#22 (comment)

Simply manually copying over the fmod dylib files

(cp Source/Audio/FMOD/libs/osx/libfmod.dylib bin/Release/net8.0/osx-arm64/)

and then setting the flag as mentioned in the comment linked above:

cp Source/Audio/FMOD/libs/osx/libfmod*.dylib bin/Release/net8.0/osx-arm64/ # can change to Debug if not running release build

# This actually fixed the crash, assuming a homebrew installation
export DOTNET_ROOT="/opt/homebrew/opt/dotnet/libexec"

Worked for me, hopefully helps others.

Have a great day!

EDIT: This seemed to have just allowed me to run it, on the third run it actually segfaulted as documented by others. Leave the comment in case it actually helps in any way, happy to remove if not useful as well

I think this line would need to be amended to include osx-arm64:
main/Celeste64.csproj#L30

For arm64 compatibility we can use $(RuntimeIdentifier.StartsWith('osx') instead of $(RuntimeIdentifier) == 'osx-x64'

For arm64 compatibility we can use $(RuntimeIdentifier.StartsWith('osx') instead of $(RuntimeIdentifier) == 'osx-x64'

Nice, I've done that! That sounds correct.

Hot off the M1 presses with a clean checkout of 1ee558c, it's a SEGFAULT log! (It has a different exit code compared to OP, mind. I can make a new issue if this isn't ok)
20240203-segfault.log

To repro:

❯ dotnet run
Celeste 64 v.1.0.1
Foster: v0.1.16
Platform: Darwin 23.2.0 Darwin Kernel Version 23.2.0: Wed Nov 15 21:53:18 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T6000 (Arm64)
Framework: .NET 8.0.1
SDL: v2.30.0
OpenGL: v4.1 Metal - 88, Apple M1 Pro
FMOD Bindings: v20218
FMOD: v20218
WARNING: Output of vertex shader 'v_col' not read by fragment shader
WARNING: Output of vertex shader 'v_type' not read by fragment shader

WARNING: Output of vertex shader 'v_color' not read by fragment shader

Loaded Assets in 396ms

The window opened for a few hundred milliseconds (attempted to go fullscreen) before producing the crash log. Happens with and without sudo.

Managed to track down the offending vertex shader lines. The top two refer to v_col and v_type from Edge.glsl and the v_color is from Default.glsl

Yeah I'm currently still at a loss for what is causing the segfault. The actual error seems to occur when it tries to swap buffers. On my end that code is very straightforward:

void FosterFrameEnd_OpenGL()
{
	FosterState* state = FosterGetState();

	// bind 0 to the frame buffer as per SDL's suggestion for macOS:
	// https://wiki.libsdl.org/SDL2/SDL_GL_SwapWindow#remarks
	FosterBindFrameBuffer(NULL);

	SDL_GL_SwapWindow(state->window);
}

so something must be going wrong either in how stuff is setup, or there's some other potential issue I'm unaware of.

Hello everyone!

I'm trying to run the game on my Macbook Pro (2021, M1 Pro) and I'm getting the same segfault error when executing the game. I've played a little bit with the source code and found out two things.

1. Fixed Time Step
First off, the segfault doesn't seem to occur when the game is run with Time.FixedStep = false; (Game.cs). Without it the game can be consistently run and played (and by the way, it's adorable!).
I even tried to change the Titlescreen.Render method to something super simple like:

public override void Render(Target target)
{
    target.Clear(Color.White, 1, 0, ClearMask.All);
    batch.Render(target);
    batch.Clear();
}

and still this only works consistently when the fixed step is off, even though in this case an error is logged reporting UNSUPPORTED (log once): POSSIBLE ISSUE: unit 0 GLD_TEXTURE_INDEX_2D is unloadable and bound to sampler type (Float) - using zero texture because texture unloadable.

2. Logging (segfault unrelated)
The other thing is unrelated to the segfault and related to the Foster library (but maybe I'll report this on the library GitHub page). When using the latest version cloned from the repo, an error occurs when the library tries to log a message:

Process terminated. A callback was made on a garbage collected delegate of type 'Foster.Framework!Foster.Framework.Platform+FosterLogFn::Invoke'.
Repeat 2 times:
--------------------------------
   at Foster.Framework.Platform.FosterShaderCreate(FosterShaderData ByRef)
--------------------------------
   at Foster.Framework.Shader..ctor(Foster.Framework.ShaderCreateInfo ByRef)
   at Celeste64.Assets.LoadShader(System.String)
   at Celeste64.Assets.Load()
   at Celeste64.Startup.BeginGame()
   at Celeste64.Startup.Update()
   at Celeste64.Game.Update()
   at Foster.Framework.App.<Tick>g__Update|69_0(System.TimeSpan)
   at Foster.Framework.App.Tick()
   at Foster.Framework.App.Run(System.String, Int32, Int32, Boolean)
   at Foster.Framework.App.Run[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.String, Int32, Int32, Boolean)
   at Celeste64.Program.Main(System.String[])

The error related code seems to be in the case of the FosterLogInfo function fstate.logInfo(msg); (foster_platform.c). The same applies to the other log functions, since commenting out the log instructions seems to solve the problem.

Hope some of this will be useful in making the game playable on MacOS also! 😄

This is great, thanks for the details! The fixed timestep issue is interesting ... I'm not sure how that would be causing it but I'll investigate.

The Logging error is because the C# GC is collecting a delegate used only by C, but I thought I had fixed that by holding onto the reference. Do you know if you were running on a the latest version?

Some news 📰

1. Logging
I was not working with the latest version of Foster: the logging error is fixed with this one!

2. segfault
Managed to find a way to make the game run consistently when in fixed timestep mode by changing the condition in App.cs (line 394) to:

if (Time.FixedStep && Time.Frame > 0)

Doing the first update using the "unfixed" strategy and then switching back to the fixed one seems to resolve the issue.

Maybe the game is doing something when updating that if done multiple times on the first tick can cause the segfault error?
Did some test using the Titlescreen scene (which is the one loaded after the Startup) and with the following Test scene:

namespace Celeste64;

public class Test : Scene
{
    private readonly Batcher batch = new();

    public Test()
    {
        Music = "event:/music/mus_title";
    }

    public override void Update()
    {
      if (Controls.Cancel.Pressed)
      {
        App.Exit();
      }
    }

    public override void Render(Target target)
    {
        target.Clear(Color.White);
        batch.Circle(new Vector2(100, 100), 30.0f, 100, Color.Black);
        batch.Render(target);
        batch.Clear();
    }
}

Even though this might not be a viabile or a reasonable solution, I hope this could help in investigating this error further 💻

I wonder if the issue occurs if it Renders before Update is ever called. I notice that basically your fix just forces Update to be called once at the start of the application before Render is. I still have no idea why that would make a difference, but this is a really useful insight!

Maybe running a glFlush before calling SDL_GL_SwapWindow could help, but now I'm basically just guessing randomly.