Skip to content

Commit

Permalink
gui: Watch vm state to terminate when it's stopped
Browse files Browse the repository at this point in the history
The GUI code in virtualization_view.m is notified when there was a guest
initiated shutdown ('guestDidStopVirtualMachine') and when there was a
virtualization error ('didStopWithError').

When calling Stop(), the VM is forcefully stopped (similar to pulling
the plug on real hardware). This action is neither a guest initiated
shutdown, nor a virtualization error, so the GUI code does not catch
it. This means after calling vm.Stop(), the GUI main loop will keep
running, and the application using Code-Hex/vz will never exit.

This commit fixes this by adding an observer for VM state changes, and
by calling 'terminate' when the VM state becomes 'stopped' or 'error'.

This fixes Code-Hex#150
  • Loading branch information
cfergeau committed Mar 29, 2024
1 parent bf698c9 commit 7ebed7c
Showing 1 changed file with 24 additions and 0 deletions.
24 changes: 24 additions & 0 deletions virtualization_view.m
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,30 @@ - (instancetype)init

@end

API_AVAILABLE(macos(12.0))
@interface VMStateObserver : NSObject
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
@end

@implementation VMStateObserver
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
{
if ([keyPath isEqualToString:@"state"]) {
int newState = (int)[change[NSKeyValueChangeNewKey] integerValue];
if (newState == VZVirtualMachineStateStopped || newState == VZVirtualMachineStateError) {
[NSApp performSelectorOnMainThread:@selector(terminate:) withObject:context waitUntilDone:NO];
[object removeObserver:self forKeyPath:@"state"];
}
}
}
@end

@implementation AppDelegate {
VZVirtualMachine *_virtualMachine;
VZVirtualMachineView *_virtualMachineView;
CGFloat _windowWidth;
CGFloat _windowHeight;
VMStateObserver *_observer;
}

- (instancetype)initWithVirtualMachine:(VZVirtualMachine *)virtualMachine
Expand All @@ -179,6 +198,11 @@ - (instancetype)initWithVirtualMachine:(VZVirtualMachine *)virtualMachine
self = [super init];
_virtualMachine = virtualMachine;
_virtualMachine.delegate = self;
_observer = [[VMStateObserver alloc] init];
[virtualMachine addObserver:_observer
forKeyPath:@"state"
options:NSKeyValueObservingOptionNew
context:(void *)self];

// Setup virtual machine view configs
VZVirtualMachineView *view = [[[VZVirtualMachineView alloc] init] autorelease];
Expand Down

0 comments on commit 7ebed7c

Please sign in to comment.