Kaynağa Gözat

macOS: per-vm debug logging

Resolves #575
osy 4 yıl önce
ebeveyn
işleme
4ab1b0570e

+ 3 - 0
Managers/UTMLogging.m

@@ -16,6 +16,7 @@
 
 
 #import <pthread.h>
 #import <pthread.h>
 #import <stdio.h>
 #import <stdio.h>
+#import <TargetConditionals.h>
 #import <unistd.h>
 #import <unistd.h>
 #import "UTMLogging.h"
 #import "UTMLogging.h"
 
 
@@ -47,7 +48,9 @@ void UTMLog(NSString *format, ...) {
     if (!initialized) {
     if (!initialized) {
         initialized = YES;
         initialized = YES;
         gLoggingInstance = [[UTMLogging alloc] init];
         gLoggingInstance = [[UTMLogging alloc] init];
+#if TARGET_OS_IPHONE // not supported on macOS
         [gLoggingInstance redirectStandardFds];
         [gLoggingInstance redirectStandardFds];
+#endif
     }
     }
 }
 }
 
 

+ 2 - 0
Managers/UTMQemu.h

@@ -20,6 +20,7 @@
 typedef void * _Nullable (* _Nonnull UTMQemuThreadEntry)(void * _Nullable args);
 typedef void * _Nullable (* _Nonnull UTMQemuThreadEntry)(void * _Nullable args);
 
 
 @class UTMConfiguration;
 @class UTMConfiguration;
+@class UTMLogging;
 
 
 NS_ASSUME_NONNULL_BEGIN
 NS_ASSUME_NONNULL_BEGIN
 
 
@@ -32,6 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic) NSInteger status;
 @property (nonatomic) NSInteger status;
 @property (nonatomic) NSInteger fatal;
 @property (nonatomic) NSInteger fatal;
 @property (nonatomic) UTMQemuThreadEntry entry;
 @property (nonatomic) UTMQemuThreadEntry entry;
+@property (nonatomic, nullable) UTMLogging *logging;
 
 
 - (instancetype)init;
 - (instancetype)init;
 - (instancetype)initWithArgv:(NSArray<NSString *> *)argv NS_DESIGNATED_INITIALIZER;
 - (instancetype)initWithArgv:(NSArray<NSString *> *)argv NS_DESIGNATED_INITIALIZER;

+ 9 - 2
Managers/UTMQemu.m

@@ -148,7 +148,7 @@
                 NSString *err = [NSString stringWithUTF8String:dlerror()];
                 NSString *err = [NSString stringWithUTF8String:dlerror()];
                 completion(NO, err);
                 completion(NO, err);
             } else if (self.fatal || self.status) {
             } else if (self.fatal || self.status) {
-                completion(NO, [NSString stringWithFormat:NSLocalizedString(@"QEMU exited from an error: %@", @"UTMQemu"), [[UTMLogging sharedInstance] lastErrorLine]]);
+                completion(NO, [NSString stringWithFormat:NSLocalizedString(@"QEMU exited from an error: %@", @"UTMQemu"), self.logging.lastErrorLine]);
             } else {
             } else {
                 completion(YES, nil);
                 completion(YES, nil);
             }
             }
@@ -166,9 +166,16 @@
         completion(NO, error.localizedDescription);
         completion(NO, error.localizedDescription);
         return;
         return;
     }
     }
+    NSFileHandle *standardOutput = self.logging.standardOutput.fileHandleForWriting;
+    NSFileHandle *standardError = self.logging.standardError.fileHandleForWriting;
     [[_connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) {
     [[_connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) {
         completion(NO, error.localizedDescription);
         completion(NO, error.localizedDescription);
-    }] startQemu:name libraryBookmark:libBookmark argv:self.argv onExit:completion];
+    }] startQemu:name standardOutput:standardOutput standardError:standardError libraryBookmark:libBookmark argv:self.argv onExit:^(BOOL success, NSString *msg){
+        if (!success && !msg) {
+            msg = self.logging.lastErrorLine;
+        }
+        completion(success, msg);
+    }];
 }
 }
 
 
 - (void)start:(nonnull NSString *)name completion:(void(^)(BOOL,NSString *))completion {
 - (void)start:(nonnull NSString *)name completion:(void(^)(BOOL,NSString *))completion {

+ 1 - 0
Managers/UTMVirtualMachine.h

@@ -22,6 +22,7 @@
 #import "UTMInputOutput.h"
 #import "UTMInputOutput.h"
 
 
 @class UTMConfiguration;
 @class UTMConfiguration;
+@class UTMLogging;
 @class UTMQemuManager;
 @class UTMQemuManager;
 @class UTMScreenshot;
 @class UTMScreenshot;
 
 

+ 6 - 1
Managers/UTMVirtualMachine.m

@@ -51,7 +51,7 @@ NSString *const kSuspendSnapshotName = @"suspend";
 @property (nonatomic, readonly) UTMQemuManager *qemu;
 @property (nonatomic, readonly) UTMQemuManager *qemu;
 @property (nonatomic, readwrite, nullable) UTMQemuSystem *system;
 @property (nonatomic, readwrite, nullable) UTMQemuSystem *system;
 @property (nonatomic, readwrite) UTMViewState *viewState;
 @property (nonatomic, readwrite) UTMViewState *viewState;
-@property (nonatomic, weak) UTMLogging *logging;
+@property (nonatomic) UTMLogging *logging;
 @property (nonatomic, readonly, nullable) id<UTMInputOutput> ioService;
 @property (nonatomic, readonly, nullable) id<UTMInputOutput> ioService;
 @property (nonatomic, readwrite) BOOL busy;
 @property (nonatomic, readwrite) BOOL busy;
 @property (nonatomic, readwrite, nullable) UTMScreenshot *screenshot;
 @property (nonatomic, readwrite, nullable) UTMScreenshot *screenshot;
@@ -106,7 +106,11 @@ NSString *const kSuspendSnapshotName = @"suspend";
     if (self) {
     if (self) {
         _will_quit_sema = dispatch_semaphore_create(0);
         _will_quit_sema = dispatch_semaphore_create(0);
         _qemu_exit_sema = dispatch_semaphore_create(0);
         _qemu_exit_sema = dispatch_semaphore_create(0);
+#if TARGET_OS_IPHONE
         self.logging = [UTMLogging sharedInstance];
         self.logging = [UTMLogging sharedInstance];
+#else
+        self.logging = [UTMLogging new];
+#endif
     }
     }
     return self;
     return self;
 }
 }
@@ -262,6 +266,7 @@ error:
     
     
     if (!self.system) {
     if (!self.system) {
         self.system = [[UTMQemuSystem alloc] initWithConfiguration:self.configuration imgPath:self.path];
         self.system = [[UTMQemuSystem alloc] initWithConfiguration:self.configuration imgPath:self.path];
+        self.system.logging = self.logging;
 #if !TARGET_OS_IPHONE
 #if !TARGET_OS_IPHONE
         [self.system setupXpc];
         [self.system setupXpc];
 #endif
 #endif

+ 1 - 0
Platform/UTMData.swift

@@ -368,6 +368,7 @@ class UTMData: ObservableObject {
             #if os(macOS)
             #if os(macOS)
             imgCreate.setupXpc()
             imgCreate.setupXpc()
             #endif
             #endif
+            imgCreate.logging = UTMLogging()
             imgCreate.start { (_success, _msg) in
             imgCreate.start { (_success, _msg) in
                 success = _success
                 success = _success
                 msg = _msg
                 msg = _msg

+ 3 - 1
QEMUHelper/QEMUHelper.m

@@ -70,7 +70,7 @@
     completion(YES, bookmark, url.path);
     completion(YES, bookmark, url.path);
 }
 }
 
 
-- (void)startQemu:(NSString *)binName libraryBookmark:(NSData *)libBookmark argv:(NSArray<NSString *> *)argv onExit:(void(^)(BOOL,NSString *))onExit {
+- (void)startQemu:(NSString *)binName standardOutput:(NSFileHandle *)standardOutput standardError:(NSFileHandle *)standardError libraryBookmark:(NSData *)libBookmark argv:(NSArray<NSString *> *)argv onExit:(void(^)(BOOL,NSString *))onExit {
     NSURL *qemuURL = [[NSBundle mainBundle] URLForAuxiliaryExecutable:binName];
     NSURL *qemuURL = [[NSBundle mainBundle] URLForAuxiliaryExecutable:binName];
     if (!qemuURL || ![[NSFileManager defaultManager] fileExistsAtPath:qemuURL.path]) {
     if (!qemuURL || ![[NSFileManager defaultManager] fileExistsAtPath:qemuURL.path]) {
         NSLog(@"Cannot find executable for %@", binName);
         NSLog(@"Cannot find executable for %@", binName);
@@ -93,6 +93,8 @@
     NSTask *task = [NSTask new];
     NSTask *task = [NSTask new];
     task.executableURL = qemuURL;
     task.executableURL = qemuURL;
     task.arguments = argv;
     task.arguments = argv;
+    task.standardOutput = standardOutput;
+    task.standardError = standardError;
     //task.environment = @{@"DYLD_LIBRARY_PATH": libraryPath.path};
     //task.environment = @{@"DYLD_LIBRARY_PATH": libraryPath.path};
     task.qualityOfService = NSQualityOfServiceUserInitiated;
     task.qualityOfService = NSQualityOfServiceUserInitiated;
     task.terminationHandler = ^(NSTask *task) {
     task.terminationHandler = ^(NSTask *task) {

+ 1 - 1
QEMUHelper/QEMUHelperProtocol.h

@@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
 @protocol QEMUHelperProtocol
 @protocol QEMUHelperProtocol
 
 
 - (void)accessDataWithBookmark:(NSData *)bookmark securityScoped:(BOOL)securityScoped completion:(void(^)(BOOL, NSData * _Nullable, NSString * _Nullable))completion;
 - (void)accessDataWithBookmark:(NSData *)bookmark securityScoped:(BOOL)securityScoped completion:(void(^)(BOOL, NSData * _Nullable, NSString * _Nullable))completion;
-- (void)startQemu:(NSString *)binName libraryBookmark:(NSData *)libBookmark argv:(NSArray<NSString *> *)argv onExit:(void(^)(BOOL,NSString *))onExit;
+- (void)startQemu:(NSString *)binName standardOutput:(NSFileHandle *)standardOutput standardError:(NSFileHandle *)standardError libraryBookmark:(NSData *)libBookmark argv:(NSArray<NSString *> *)argv onExit:(void(^)(BOOL,NSString *))onExit;
     
     
 @end
 @end