anaseto/harmonist

harmonist-0.4.0-windows_amd64-tiles freezes at startup

Closed this issue · 12 comments

Hello Anaseto :)

I was excited to see the standalone version with tiles – I'm not a fan of playing games in browser.

Unfortunately, the tiled version doesn't work for me. At the title screen, it freezes. Sometimes from the very beginning of running the executable, sometimes it seems to freeze after keypress; personally, I don't think it makes difference, it's just janky Windows that sometimes needs a bit more time to detect that the app is not responding.

There is no error message, neither as a po-up nor in the console window. The terminal version works just fine.

I know this bug report lacks details, but there is exactly nothing going on – it just hangs, like it encountered infinite loop.

I'm playing on Windows 10, 64-bit, Radeon R380X, Ryzen 5600.

Hi! Thanks for testing on windows!

I kind of feared some issue on windows for the tiles version: I just cross-compiled from Linux, and because of the SDL component, it wasn't pure Go cross-compilation, I had never tried that before.

Sadly, it's difficult for me to debug this. While it's most probably related to a failed cross-compilation, I cannot really discard the possibility of some other issue without trying to compile on a windows machine directly. If you want to give it a try, you'll need an SDL installation and then execute go install --sdl in harmonist cloned repository.

Anyways, thanks again for the report!

Ops, I wrote a typos in previous comment: the build command is go install --tags sdl.

I can try to build it. I'm not proficient in C, I was barely able to install BearLibTerminal to use it with CGO :)

I'll try to hack my way to compile Harmonist with SDL, and I'll let you know the results.

OK, the SDL installation process was much easier than I expected. The actual size of the binary changed, now it's almost 10MB (vs 5MB of original 0.4 tiled). The behaviour remains the same.

Also, I'm not sure if that's true or maybe I didn't notice it at first, the background of the empty tiles is black now. I think that the empty spaced had the same bg colour as the cells with fg glyphs. The thing is that the version originally compiled by you looks the same now – so I remember it wrong, or maybe installing SDL changed something, system-wide?

obraz

Tomorrow I'll try to debug the code a bit, but first I need to learn how to pass tags sdl to Delve.

I think I found the issue, by naive fmt.Println-based debugging.

The problem seems to lie in the (app *App) Start(ctx context.Context) (err error) method in the gruid/ui package. In the for loop, to be accurate.

The first pass seems to be OK, without errors. But starting the second pass, the game can't find any value that fulfills the select statement. Select in this for loop doesn't have the default case, so it effectively blocks the execution of a program.

To test it, you can simply add the default case with some debugging printing (e.g. "No valid values found"), and fmt.Prinltn("select...") just before the select statement. It will 1) unblock the execution of a program, and 2) fill the console with an infinite stream of "select... No valid values found".

	// Update on message then Draw main loop
	for {
		fmt.Println("select...")
		select {
		case <-ctx.Done():
			fmt.Println("  case <=ctx.Done()")
			return err
		case err := <-errs:
			fmt.Println("  err := <-errs")
			cancel()
			return err
		case msg := <-msgs:
			fmt.Println("msg := <-msgs")
			if msg == nil {
				continue
			}

			// Handle quit message
			if _, ok := msg.(msgEnd); ok {
				cancel()
				return err
			}

			// Process batched effects
			if batchedEffects, ok := msg.(msgBatch); ok {
				for _, eff := range batchedEffects {
					select {
					case effects <- eff:
					case <-ctx.Done():
						break
					}
				}
				continue
			}

			// force redraw on screen message
			_, exposed := msg.(MsgScreen)

			eff := app.model.Update(msg)
			if eff != nil {
				select {
				case effects <- eff: // process effect (if any)
				case <-ctx.Done():
					continue
				}
			}

			gd := app.model.Draw()
			frame := app.computeFrame(gd, exposed)
			if len(frame.Cells) > 0 {
				app.flush(frame)
			}
		default:
			fmt.Println("No valid values found")
		}
	}
}

Wow, thanks for your work! This helps a lot, I may have found the issue.

The main loop normally waits for input and window messages. If messages are not being received in the main loop, that should mean that github.com/anaseto/gruid-sdl is not sending them properly. If the background is partially black, that means the message produced on window exposition wasn't sent properly.

I've commited a debugging pacth in gruid-sdl in a new branch. Actually, it may even somehow mitigate the issue with freezing itself: I've added a timeout when sending messages, so that it should not freeze for more than 100ms in case of delay. I've left a couple of debugging messages.

You can try it by using the fixing-windows-freeze branch of github.com/anaseto/gruid-sdl.

The actual size of the binary changed, now it's almost 10MB (vs 5MB of original 0.4 tiled).

That could be because I removed debugging symbols and such from the tiles binary, to make it lighter.

As to why this happens, I'm still not sure, but I think it could be related to thread-safety of the SDL2's input subsystem. The video-subsystem is clearly documented to never be thread-safe (on any platform), so I made it so that all video-related functions run on the main routine. For the input sub-system, the documentation is less clear, it seems to state that it depends on the platform. Because on Linux and OpenBSD I had not issues, I assumed input was thread safe on those, so probably also on windows. It may well be that my assumption was incorrect.

If my intuition is correct, the proper fix will be to somehow run the message input loop in the main routine.

I've pushed a new version of both gruid and gruid-sdl such that the message input handling runs in the main thread. This will hopefully properly fix the issue. Otherwise, it will at least discard a potential cause, tough I really hope it was related to this, as with such a weird issue, a thread-related problem is the only thing that comes to my mind.

I've pushed a commit to harmonist's repository, so that go install will now pull the new versions of gruid and gruid-sdl. You should be able to update to the patched version with just git pull and then go install --tags sdl in harmonist's repo.

Thank you for making the playtesting as easy as possible :) And I'm really glad I could help.

I supposed that the underlying source of the problem may be a difference between posix and Windows threading model, yet I don't know much about multithreading apps so didn't want to blindly mess with the code.

I built the latest master with updated libs, and it seems to work properly. The background is not black anymore, and I can progress past the main screen.

obraz

obraz

I hope we can close this issue, but I'll make some playtesting first.

Great!!

Well, I was dying quickly and never went far, but no issues encountered so far. Thank you for fixing it quickly :)

Since it seems to work well, I'll probably soon make a new minor release and add a new download for the tiles version with the fix. Thanks you too for playtesting!