amiberry
amiberry copied to clipboard
Amiberry on macOS M1 crashes when I try to use Drawbridge (Greaseweazle) real drive as DF0
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 Unfortunately I have no way of testing this, without any M1 platform.
@Yserra
Can I ask what version of Xcode you are using?
Got the same error now on the pre-compiled latest release. Just crashes
@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 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 It hasn't been tested on macOS actually. There may be a bug that manifests itself there.
Can I ask what version of Xcode you are using?
I'm using Xcode version 14.3.1 (14E300c)
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.
Still an issue..
@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).
No difference.. Hard crash, either using the x86 binary or M1
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?
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.
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
@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.
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.
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!
@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).
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!
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.
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?
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;
}
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);
@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).
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 @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 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 Done 1 minute before your reply ;)
@svenson-a did you uncomment the queueCommand(QueueCommand::qcResetDrive); Line as well? You don’t mention you had