amiberry icon indicating copy to clipboard operation
amiberry copied to clipboard

Amiberry on macOS M1 crashes when I try to use Drawbridge (Greaseweazle) real drive as DF0

Open Yserra opened this issue 2 years ago • 17 comments
trafficstars

Describe the bug Amiberry on macOS M1 crashes when I try to use Drawbridge (Greaseweazle) real drive as DF0. After configuring DF0 as DrawBridge/Greaseweazle device (I hear the drive doing something, like going to track 0 or something), I click Start, on regular Amiga 500, Kick 1.3 emulation Amiberry crashes immediately with a regular macOS window alert entitled "Amiberry has quitted unexpectedly" and a long log.

To Reproduce On Mac M1, macOS Ventura 13.4, after building the source code downloaded on June 11th, 2023 from this GitHub, After having verified that expected Kickstarts are installed into ~/Documents/Amiberry/Kickstarts After having verified that the Greaseweazle solution and the 3.5 drive are working as expected (write an .adf to disk, read it back) After having verified that random .adf images are running as expected as DF0 under the Amiga 500 emulation on Amiberry Go to Floppy Drives panel Select DF0: FB: Compatible Select DrawBridge driver : Greaseweazle hear a short noise from the drive Click "Start" Debug macOS window shows on screen

Errors listed: Process: Amiberry [5944] Path: /Applications/Emulation/*/Amiberry.app/Contents/MacOS/Amiberry Identifier: com.blitterstudio.amiberry Version: 5.6.1 (???) Code Type: ARM-64 (Native) Parent Process: launchd [1] User ID: 501

Date/Time: 2023-06-11 02:00:06.3202 +0200 OS Version: macOS 13.4 (22F66) Report Version: 12 Anonymous UUID: 9442A17A-FDF9-165D-8363-3A94507A2258

Time Awake Since Boot: 6200 seconds

System Integrity Protection: enabled

Crashed Thread: 0 Dispatch queue: com.apple.main-thread

Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000

Application Specific Information: abort() called

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libsystem_kernel.dylib 0x19b5e0724 __pthread_kill + 8 1 libsystem_pthread.dylib 0x19b617c28 pthread_kill + 288 2 libsystem_c.dylib 0x19b525ae8 abort + 180 3 libc++abi.dylib 0x19b5d0b84 abort_message + 132 4 libc++abi.dylib 0x19b5c03b4 demangling_terminate_handler() + 320 5 libobjc.A.dylib 0x19b29703c _objc_terminate() + 160 6 libc++abi.dylib 0x19b5cff48 std::__terminate(void (*)()) + 16 7 libc++abi.dylib 0x19b5cfeec std::terminate() + 56 8 Amiberry 0x100f06b70 0x1007c8000 + 7596912 9 Amiberry 0x10085bf60 0x1007c8000 + 606048 10 Amiberry 0x10085bc1c 0x1007c8000 + 605212 11 Amiberry 0x10084e9b4 0x1007c8000 + 551348 12 Amiberry 0x10083894c 0x1007c8000 + 461132 13 Amiberry 0x100ac0fd8 0x1007c8000 + 3117016 14 Amiberry 0x100914270 0x1007c8000 + 1360496 15 Amiberry 0x100a1a9cc 0x1007c8000 + 2435532 16 dyld 0x19b2bff28 start + 2236 .... Thread 0 crashed with ARM Thread State (64-bit): x0: 0x0000000000000000 x1: 0x0000000000000000 x2: 0x0000000000000000 x3: 0x0000000000000000 x4: 0x000000019b5d4618 x5: 0x000000016f636600 x6: 0x746e656d75677261 x7: 0x000000016f6365d8 x8: 0x8bd8e91c6139770f x9: 0x8bd8e91d9758290f x10: 0x0000000000000200 x11: 0x0000000000000030 x12: 0x0000000000000030 x13: 0x0000000000022020 x14: 0x00000000ffffffff x15: 0x0000000000000000 x16: 0x0000000000000148 x17: 0x00000001fb138f60 x18: 0x0000000000000000 x19: 0x0000000000000006 x20: 0x00000001f6615e00 x21: 0x0000000000000103 x22: 0x00000001f6615ee0 x23: 0x0000000105e2b550 x24: 0x0000000104227fc0 x25: 0x0000000000000000 x26: 0x000000010424ab38 x27: 0x000000010424a9ec x28: 0x000000010424aa08 fp: 0x000000016f636570 lr: 0x000000019b617c28 sp: 0x000000016f636550 pc: 0x000000019b5e0724 cpsr: 0x40001000 far: 0x000000010102c000 esr: 0x56000080 Address size fault

Expected behavior Should run an emulated Amiga 500 booting from the real floppy drive attached to Greaseweazle board (as it perfectly does with the same Greaseweazle board and the same drive on my Raspberry Pi 4)

Additional context Tested with same failure on two different Greaseweazle boards: 1/ gw info for first board: Host Tools: 1.13 Device: Port: /dev/cu.usbmodem2101 Model: Greaseweazle F7 v3 "Thunderbolt" MCU: 216MHz, 256kB SRAM Firmware: 1.3 Serial: GW000F002A4E30501420343135 USB Rate: Full Speed (12 Mbit/s)

2/ gw info for second board: Host Tools: 1.13 Device: Port: /dev/cu.usbmodem1201 Model: Greaseweazle V4 MCU: AT32F403A, 216MHz, 96kB SRAM Firmware: 1.3 Serial: GW00B5426F4C87400007748716 USB Rate: Full Speed (12 Mbit/s)

Yserra avatar Jun 11 '23 00:06 Yserra

@Yserra Unfortunately I have no way of testing this, without any M1 platform.

midwan avatar Jun 11 '23 16:06 midwan

@Yserra

Can I ask what version of Xcode you are using?

giantclambake avatar Jun 13 '23 06:06 giantclambake

Got the same error now on the pre-compiled latest release. Just crashes

n0rt0nthec4t avatar Jun 15 '23 00:06 n0rt0nthec4t

@n0rt0nthec4t That's probably expected, since no changes related to this were made. It's hard to fix something if I don't know what's causing it and I can't recreate it here... :(

midwan avatar Jun 15 '23 06:06 midwan

@midwan we know that in a past commit, drawbridge support was updated for macOS, however, since no binary builds were released since that commit until now, haven't had a chance to test it. Also crashes on x86 macOS, and seems to indicate a memory leak

How was the updated support for drawbridge on macOS tested before committed?

n0rt0nthec4t avatar Jun 20 '23 23:06 n0rt0nthec4t

@n0rt0nthec4t It hasn't been tested on macOS actually. There may be a bug that manifests itself there.

midwan avatar Jun 21 '23 18:06 midwan

Can I ask what version of Xcode you are using?

I'm using Xcode version 14.3.1 (14E300c)

Yserra avatar Jun 23 '23 01:06 Yserra

You might want to test with the latest updates done recently. You can now select the serial port to use, instead of having it always in Auto-Detect. That helped in some cases where Auto-Detect would fail (e.g. due to lack of permissions). The profiles are also now generated dynamically depending on your options, so some things that might have been broken before should be fixed with that.

midwan avatar Dec 26 '23 15:12 midwan

Still an issue..

n0rt0nthec4t avatar Dec 30 '23 05:12 n0rt0nthec4t

@n0rt0nthec4t / @Yserra Can you try manually selecting the serial port, instead of using the Auto-Detect option (which is the default)? The latest updates allow you to do that, and this was the source of some permissions issues previously (auto-detect was scanning all serial ports and properties of them, but in some cases the normal user didn't have permissions to do that).

midwan avatar Jan 19 '24 21:01 midwan

No difference.. Hard crash, either using the x86 binary or M1

n0rt0nthec4t avatar Jan 22 '24 21:01 n0rt0nthec4t

Hi midwan, i started Amiberry over the shell on Mac M1. Tested with Greazweazle V4.1 on Amiberry v5.6.7 and pre-release v6.1.3. Maybe this output helps you?

libc++abi: terminating due to uncaught exception of type std::__1::system_error: condition_variable wait failed: Invalid argument

I'am not a coder. But if there is a possibility to help you, let me know. Is there a possibility for logging or debugging?

svenson-a avatar Feb 19 '24 08:02 svenson-a

Logging can be enabled in the amiberry.conf file, either manually (by editing the file and setting the write_logfile option to yes, or from the GUI by going to Paths->Enable logging and then Quitting the emulator (so when it starts up next, it will log stuff from the beginning).

If enabled, Amiberry will try to create a file named amiberry.log in the directory it start up from. In macOS specifically, that should be in the Documents folder normally.

midwan avatar Feb 19 '24 17:02 midwan

Compiled with Xcode 15.2 "make -j8 PLATFORM=osx-m1" I attached the amiberry.log

amiberry.log

svenson-a avatar Feb 19 '24 19:02 svenson-a

After a little bit playing around i got access to the floppy and were able to load from a floppy disk. Used a self compiled version v5.6.7

Here are the steps:

1.) Started amiberry without any disk selected (no DF0:, no DF1: etc.) 2.) Start an A500 with Kick 1.3 3.) When you see the kickstart screen go back to settings with "F12" for the amiberry menu 4.) Go to menu point "Floppy drives" Activate DF0: with DB:Compatible 5.) IMPORTANT: Go to DrawBridge selection on the same page use the dropdown "DrawBridge driver:" and select an "Greaseweazle" entry - BUT NOT the first one - I don't know why, but you will see more than one "Greaseweazle" entry's 6.) Click on Resume 7.) Nothing happens - BUT NOW IT COMES 8.) Go Back to the menu again with "F12" 9.) Now select the FIRST entry "Greaseweazle" in drop down "DrawBridge driver:" 10.) Click on Resume 11.) Amiberry starts to load from floppy disk!

Look at the attached log file! You can see the entry's disk read DMA started, drvmask=1 motormask=0 PC=00fea22e

amiberry+greaseweazle

amiberry.log

svenson-a avatar Feb 19 '24 23:02 svenson-a

@svenson-a Thanks for the feedback. That list should not contain double entries of course, so it's really weird. The list is populated by the FloppyBridge driver itself, so I wonder if it's something there that triggers this problem, or something on Amiberry's GUI side instead.

So, I've made a small change, to make sure that list is cleared before it gets populated. Please test with the latest sources again, and see if that helps.

midwan avatar Feb 20 '24 22:02 midwan

Thank you for changing the source that fast! I compiled from the new sources. The list is now, as you expected, filled only with one entry. Unfortunately it still crashes when selecting "DrawBridge driver: Greaseweazle" after starting. But there is a short read attempt on the floppy before it crashes. You can see it in the log file I attached.

amiberry.log

svenson-a avatar Feb 20 '24 22:02 svenson-a

After setting up Visual Studio Code with the following extensions: "C/C++" and "Makefile Tools", I was able to do some debugging on the whole Amiberry code. I found out, that when i comment out the function reset_drive (dr); within the function void DISK_reset (void) from the disk.cpp file, I am able to access the Greaseweazle interface without any problems on a Mac M1. No more crash! vscode_debugging_amiberry

svenson-a avatar Feb 22 '24 09:02 svenson-a

@svenson-a Thanks for narrowing it down, that helps! The reset_drive is required of course, and I think what triggers the problem is probably inside it, and specifically within this part:

#ifdef FLOPPYBRIDGE
	if (drv->bridge) {
		drv->bridge->resetDrive(drv->cyl);
		drv->indexhackmode = 0;
		drv->num_tracks = drv->bridge->getMaxCylinder() * 2;
		drv->filetype = ADF_FLOPPYBRIDGE;
		drv->tracklen = drv->bridge->maxMFMBitPosition();
		drv->ddhd = drv->bridge->getDriveTypeID() == FloppyDiskBridge::DriveTypeID::dti35HD ? 2 : 1;
	}
#endif

Though I still have no explanation on why it would fail for you (and apparently, some users) while it works for others (including me).

midwan avatar Feb 22 '24 12:02 midwan

You are welcome. For sure it is an important function. I have done only a "quick and dirty" hack to get closer to the involved code area which causes the crash.

Thank you for such a great piece of software!

svenson-a avatar Feb 22 '24 12:02 svenson-a

Can you check if it's the drv->bridge->resetDrive(drv->cyl); step that triggering the problem for you? My guess is it's there, but it would be good to have confirmation.

midwan avatar Feb 24 '24 12:02 midwan

Yes gladly! First I have done it the hard way with commenting drv->bridge->resetDrive(drv->cyl); out. Debugger as well as compiled binary starts and works without a crash. Then I set a breakpoint at drv->bridge->resetDrive(drv->cyl); and stepped through the rest of the section. I noticed a little delay at this section within the file CommonBridgeTemplate.cpp.

// Reset the drive.  This should reset it to the state it would be at power up
bool CommonBridgeTemplate::resetDrive(int trackNumber) {
	// Delete all future writes
	{
		std::lock_guard lock(m_pendingWriteLock);
		m_pendingTrackWrites.clear();
	} 

I set the second breakpoint here m_pendingTrackWrites.clear();.

When I step through the code it generates no crash. As a started binary it crashes as known. Maybe there is some timing issue? breakpoint_01 breakpoint_02

svenson-a avatar Feb 24 '24 15:02 svenson-a

Ok I think I found the position. Maybe it is here:

m_driveResetStatusFlag.wait(lck, [this] { return m_driveResetStatus; });

This function call is in the CommonBridgeTemplate.cpp file.

When I isolate it , everything works.

// Reset the drive.  This should reset it to the state it would be at power up
bool CommonBridgeTemplate::resetDrive(int trackNumber) {
	// Delete all future writes
	{
		std::lock_guard lock(m_pendingWriteLock);
		m_pendingTrackWrites.clear();
	} 

	// Reset flag
	{
		std::lock_guard lock(m_driveResetStatusFlagLock);
		m_driveResetStatus = false;
	}
	//queueCommand(QueueCommand::qcResetDrive);

	// Wait for the reset to occur.  At this point we know the queue is also clear
	std::unique_lock lck(m_driveResetStatusFlagLock);
	//m_driveResetStatusFlag.wait(lck, [this] { return m_driveResetStatus; });

	// Ready
	return true;
}

svenson-a avatar Feb 24 '24 15:02 svenson-a

When you step into this function m_driveResetStatusFlag.wait(lck, [this] { return m_driveResetStatus; }); then you come to a system function from __mutex_base the exception is thrown with wait(__lk); __mutex_base

svenson-a avatar Feb 24 '24 18:02 svenson-a

@svenson-a Thanks for narrowing it down further. I'll invite Rob to take a peek at this, perhaps he has an idea of why this might be failing (and more specifically, why it works for some, but fails for some, as it seems).

midwan avatar Feb 27 '24 22:02 midwan

Ok, something to try, it may seem unrelated but may fix the issue.

In CommonBridgeTemplate.cpp line 288. Change the line queueReady = m_driveResetStatusFlag.wait_for(lck, queuePause, [this] { return m_queueSemaphore > 0; }); to queueReady = m_queueSemaphoreFlag.wait_for(lck, queuePause, [this] { return m_queueSemaphore > 0; });

Let me know if that helps. If so, I'll push an update to the FloppyBridge repo.

RobSmithDev avatar Feb 28 '24 08:02 RobSmithDev

@RobSmithDev @midwan Thank you for investigating deeper on that issue.

I ll put back the following function: m_driveResetStatusFlag.wait(lck, [this] { return m_driveResetStatus; }); and changed the function in line 288 to: queueReady = m_queueSemaphoreFlag.wait_for(lck, queuePause, [this] { return m_queueSemaphore > 0; });

Starting amiberry is working. After starting the emulation (A500, Kick 1.3) it freezes immediately. Its not crashing but freezing.

svenson-a avatar Feb 28 '24 20:02 svenson-a

@svenson-a Please do a test when you get a chance, and kindly report back here. If this fixes the issue, I can integrate it in the code.

midwan avatar Feb 28 '24 20:02 midwan

@midwan Done 1 minute before your reply ;)

svenson-a avatar Feb 28 '24 20:02 svenson-a

@svenson-a did you uncomment the queueCommand(QueueCommand::qcResetDrive); Line as well? You don’t mention you had

RobSmithDev avatar Feb 28 '24 21:02 RobSmithDev