johndbritton / teleport

Virtual KVM for macOS
GNU General Public License v2.0
785 stars 131 forks source link

Crash on "Configure…" #94

Open tmngtk opened 3 years ago

tmngtk commented 3 years ago

Bonjour

The app hung up when I tried to open the preference window. I debugged it and found a range exception inside [TPRemoteHost hostRect] - NSScreen * screen = [self screens][_sharedScreenIndex];

Actually I was using an external display and not any more but _sharedScreenIndex stayed 1 which is beyond the monitor count.

My work around was putting these at the end of [TPRemoteHost initWithCoder:] -

    if (_sharedScreenIndex >= [_screens count]) {
        NSLog(@"%d >= %d", _sharedScreenIndex, [_screens count]);
        _screens = nil;
        _sharedScreenIndex = -1;
        _sharedScreenPosition = NSZeroPoint;
        _localScreenIndex = -1;
    }

I also tried to reset my preferences before debugging by deleting com.abyssoft.teleport.plist at ~/Library/Preferences but it did not change the situation. Does Telepport or NSUserDefaults store the preferences at another location on Big Sur?

Thanks.

johndbritton commented 3 years ago

Thanks for the report. I'd be happy to review a PR that updates the metadata around shared screens when a display is attached or removed.

Marking this as help-wanted.

phmeier-nubank commented 3 years ago

I can see similar behaviour. It happens to me often after I have enabled / disabled external displays to the controlling machine.

phmeier-nubank commented 3 years ago

Sometimes when I put the controlling computer into suspend and then restore, teleport starts working again.

marcpbailey commented 2 years ago

I think I have another clue: this is about the index of the common 'edge' between two Teleport nodes.

I operate Teleport 1.3.3 an iMac (late 2013, macOS 11.6) and a MacBook Air M1 (2020, macOS 11.6) on a KVM that shares a single 4k display, keyboard and mouse. This lets me use (a) the iMac+display when the MacBook isn't around, or (b) the MacBook+display with Teleport to iMac, or less commonly (c) iMac+display with Teleport to MacBook. That is, I rarely use the hardware KVM except when I dock or undock the MacBook - I much prefer Teleport, naturally.

So this means that Teleport is seeing a monitor appear and disappear from both controller and target or vice-versa very frequently. The Teleport>Configure>Layout tab gets confused a lot as a result - irritating but super quick to fix usually. It's a long standing situation that dynamic display configuration state detection and repair needs work. Ideally, symmetric configuration would be a massive improvement - changing the layout on one peer should also change the layout on the trusted peer.

Anyway, I confirm this borked Configure behaviour; I haven't quite nailed down what triggers the issue, but definitely once you choose Teleport>Configure the menu hangs, no window appears and there is an uncaught exception:

updating hot border (null) for host -[TPRemoteHost:0x6000022dfd40 description] raised exception: name:NSRangeException reason:*** -[NSArrayM objectAtIndexedSubscript:]: index 1 beyond bounds [0 .. 0] backtrace:( 0 CoreFoundation 0x0000000194a8b838 exceptionPreprocess + 240 1 libobjc.A.dylib 0x00000001947b50a8 objc_exception_throw + 60 2 CoreFoundation 0x0000000194b576f8 -[NSCFString characterAtIndex:].cold.1 + 0 3 CoreFoundation 0x00000001949f96a8 -[NSCFString hasSuffix:] + 0 4 teleport 0x00000001044cb378 teleport + 144248 5 teleport 0x00000001044cbe28 teleport + 146984 6 Foundation 0x0000000195774f90 _NS_os_log_callback + 288 7 libsystem_trace.dylib 0x00000001946ac590 _os_log_fmt_flatten_NSCF + 64 8 libsystem_trace.dylib 0x00000001946abf90 _os_log_fmt_flatten_object + 216 9 libsystem_trace.dylib : show: activate:

*** -[NSArrayM objectAtIndexedSubscript:]: index 1 beyond bounds [0 .. 0] backtrace:( 0 CoreFoundation 0x0000000194a8b838 exceptionPreprocess + 240 1 libobjc.A.dylib 0x00000001947b50a8 objc_exception_throw + 60 2 CoreFoundation 0x0000000194b576f8 -[NSCFString characterAtIndex:].cold.1 + 0 3 CoreFoundation 0x00000001949f96a8 -[NSCFString hasSuffix:] + 0 4 teleport 0x00000001044cb378 teleport + 144248 5 teleport 0x00000001044cbe28 teleport + 146984 6 Foundation 0x000000019575f194 _NSDescriptionWithLocaleFunc + 100 7 CoreFoundation 0x00000001949b9f90 CFStringAppendFormatCore + 10364 8 CoreFoundation 0x0000000194af9ce8 _CFStringCreateWithFormatAndArgumentsReturningMetadata + 164 9 CoreFoundation 0x0000000194a205e0 _CFLogvEx2Predicate + 160 10 CoreFoundation 0x0000000194a20348 _CFLogvEx3 + 252 11 Foundation 0x0000000195881794 _NSLogv + 108 12 Foundation 0x00000001957a2dd4 NSLog + 56 13 teleport 0x00000001044b1a7c teleport + 39548 14 teleport 0x00000001044b2054 teleport + 41044 15 CoreFoundation 0x0000000194a01f08 CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 28 16 CoreFoundation 0x0000000194aa3e5c _CFXRegistrationPost_block_invoke + 52 17 CoreFoundation 0x0000000194aa3dc8 _CFXRegistrationPost + 456 18 CoreFoundation 0x00000001949d09d8 _CFXNotificationPost + 720 19 Foundation 0x000000019575c3c0 -[NSNotificationCenter postNotificationName:object:userInfo:] + 64 20 teleport 0x00000001044ada68 teleport + 23144 21 Foundation 0x00000001957d6b00 NSFireDelayedPerform + 444 22 CoreFoundation 0x0000000194a27828 CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION + 32 23 CoreFoundation 0x0000000194a27424 CFRunLoopDoTimer + 1076 24 CoreFoundation 0x0000000194a26eac CFRunLoopDoTimers + 392 25 CoreFoundation 0x0000000194a0c0b8 __CFRunLoopRun + 1944 26 CoreFoundation 0x0000000194a0b1a8 CFRunLoopRunSpecific + 600 27 HIToolbox 0x000000019c930b40 RunCurrentEventLoopInMode + 292 28 HIToolbox 0x000000019c9308b4 ReceiveNextEventCommon + 552 29 HIToolbox 0x000000019c930674 _BlockUntilNextEventMatchingListInModeWithFilter + 72 30 AppKit 0x00000001971fd660 _DPSNextEvent + 836 31 AppKit 0x00000001971fc000 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1292 32 AppKit 0x00000001971ede4c -[NSApplication run] + 596 33 AppKit 0x00000001971bf878 NSApplicationMain + 1064 34 libdyld.dylib 0x000000019492d430 start + 4 )

Teleport is still running and can actually still be controlled, but the menulet is frozen in a monochrome state, having never returned from trying to draw the settings window, and you have to kill and restart it. If you don't fix the issue by restoring monitor count sanity somehow this is a rinse and repeat situation.

TL;DR: I suspect this only happens if you last had the layout tab showing (ie Teleport is trying to draw the altered multiple displays), and one of the displays that was a common "edge" in the arrangement no longer exists.

To attempt to figure out what was going on I began toggling between computers with the KVM in order to switch controller/target. I ended up consistently having the problem (borked Configure) on the MacBook when it had KVM focus and was the Teleport controller. Yet I could switch KVM/control to the iMac, control the MacBook, and happily Configure away. Switch the KVM back to the MacBook, back to borked Configure.

Insight 1: Voodoo? No, the hint is that when being controlled the MacBook is reduced to one display while the iMac has two. When controlling, the MacBook has two displays while the iMac has one.

Next, I physically disconnected the display from the MacBook, but left the KVM switched to it - a state where both MacBook (controller) and iMac (target) had just one display. The Configure menu was still borked on the MacBook. Insight 2: the problem isn't about how many displays are attached to the local machine.

So I returned to MacBook as target, iMac+KVM as controller. I went in to Teleport>Configure (which again worked), and deleted the iMac display rectangles from the layout (sending them back to the top). I switched the KVM back again (MacBook+KVM) and was at last able to use Teleport>Configure once more. Insight 3: The bounds issue has something to do with enumerating the number of peer displays, but only if "arranged". I believe this is referred to in the code as a "hot border".

This has turned into a long post, but the speculative clue I'm identifying is: The problem is related to the index of the hot border between controller and target. If this display/border no longer exists, but is remembered somewhere from the past as it must be (it's not in the preference plist), the exception will be thrown.

I'm still trying to work out how to reproduce a bad hot border, and will post again if/when I do, but for now I hope this is valuable info for debugging.

BTW: I LOVE Teleport.