From b84cfb1f3c6cd1fa48d2e52b567c17384df99d82 Mon Sep 17 00:00:00 2001 From: Tae Won Ha Date: Mon, 25 Mar 2019 11:47:48 +0100 Subject: [PATCH] Add error handling when NvimServer could not be started correctly --- NvimView/NvimServer/main.c | 1 + NvimView/NvimServer/server.c | 22 ++++++++++++++ NvimView/NvimServer/server.h | 4 +++ NvimView/NvimServer/server_shared_types.h | 7 +++++ NvimView/NvimView/NvimView+UiBridge.swift | 35 +++++++++++++++++++++++ NvimView/NvimView/NvimView.swift | 2 ++ NvimView/NvimView/SharedTypes.h | 7 +++++ NvimView/NvimView/UiBridge.swift | 4 +++ 8 files changed, 82 insertions(+) diff --git a/NvimView/NvimServer/main.c b/NvimView/NvimServer/main.c index 0de38150..e19af103 100644 --- a/NvimView/NvimServer/main.c +++ b/NvimView/NvimServer/main.c @@ -30,6 +30,7 @@ int main(int argc, const char *argv[]) { "Started NvimServer '%s' and connected it with GUI '%s'.", local_port_name, remote_port_name ); + CFRunLoopRun(); os_log_debug(logger, "NvimServer exiting."); diff --git a/NvimView/NvimServer/server.c b/NvimView/NvimServer/server.c index 9f29d985..1d141d0b 100644 --- a/NvimView/NvimServer/server.c +++ b/NvimView/NvimServer/server.c @@ -84,6 +84,12 @@ static void do_autocmd_guienter(void **argv); // We declare nvim_main because it's not declared in any header files of neovim extern int nvim_main(int argc, const char **argv); +#ifdef DEBUG + +void debug_function() { +} + +#endif void server_set_nvim_args(int argc, const char **const argv) { nvim_argc = argc + 1; @@ -108,6 +114,14 @@ void server_init_local_port(const char *name) { ); CFRelease(name_cf); + if (local_port == NULL) { + send_msg_packing(NvimServerMsgIdFatalError, ^(msgpack_packer *packer) { + msgpack_pack_int64(packer, NvimServerFatalErrorCodeLocalPort); + }); + + exit(NvimServerFatalErrorCodeLocalPort); + } + cond_var_t cond_var; cond_var_init(&cond_var, 5, false); @@ -136,6 +150,14 @@ void server_init_remote_port(const char *name) { ); remote_port = CFMessagePortCreateRemote(kCFAllocatorDefault, name_cf); CFRelease(name_cf); + + if (remote_port == NULL) { + send_msg_packing(NvimServerMsgIdFatalError, ^(msgpack_packer *packer) { + msgpack_pack_int64(packer, NvimServerFatalErrorCodeRemotePort); + }); + + exit(NvimServerFatalErrorCodeRemotePort); + } } void server_destroy_remote_port() { diff --git a/NvimView/NvimServer/server.h b/NvimView/NvimServer/server.h index b346b60c..042a600f 100644 --- a/NvimView/NvimServer/server.h +++ b/NvimView/NvimServer/server.h @@ -24,4 +24,8 @@ void send_msg_packing(NvimServerMsgId msgid, pack_block body); void msgpack_pack_bool(msgpack_packer *packer, bool value); void msgpack_pack_cstr(msgpack_packer *packer, const char *cstr); +#ifdef DEBUG +void debug_function(void); +#endif + #endif // NVIMSERVER_SERVER_H diff --git a/NvimView/NvimServer/server_shared_types.h b/NvimView/NvimServer/server_shared_types.h index 6f513b17..5a1ed5f1 100644 --- a/NvimView/NvimServer/server_shared_types.h +++ b/NvimView/NvimServer/server_shared_types.h @@ -46,9 +46,16 @@ typedef CF_ENUM(NSInteger, NvimServerMsgId) { NvimServerMsgIdAutoCommandEvent, NvimServerMsgIdRpcEventSubscribed, + NvimServerMsgIdFatalError, + NvimServerMsgIdDebug1, }; +typedef CF_ENUM(NSInteger, NvimServerFatalErrorCode) { + NvimServerFatalErrorCodeLocalPort = 1, + NvimServerFatalErrorCodeRemotePort, +}; + typedef CF_ENUM(NSInteger, NvimBridgeMsgId) { NvimBridgeMsgIdAgentReady = 0, NvimBridgeMsgIdReadyForRpcEvents, diff --git a/NvimView/NvimView/NvimView+UiBridge.swift b/NvimView/NvimView/NvimView+UiBridge.swift index 13275e81..51090061 100644 --- a/NvimView/NvimView/NvimView+UiBridge.swift +++ b/NvimView/NvimView/NvimView+UiBridge.swift @@ -431,6 +431,41 @@ extension NvimView { self.eventsSubject.onNext(.rpcEventSubscribed) } + final func bridgeHasFatalError(_ value: MessagePackValue?) { + gui.async { + let alert = NSAlert() + alert.addButton(withTitle: "OK") + alert.messageText = "Error launching background neovim process" + alert.alertStyle = .critical + + if let rawCode = value?.intValue, + let code = NvimServerFatalErrorCode(rawValue: rawCode) { + + switch code { + + case .localPort: + alert.informativeText = "GUI could not connect to the background " + + "neovim process. The window will close." + + case .remotePort: + alert.informativeText = "The remote message port could not " + + "connect to GUI. The window will close." + + } + } else { + alert.informativeText = "There was an unknown error launching the " + + "background neovim Process. " + + "The window will close." + } + + alert.runModal() + self.queue.async { + self.eventsSubject.onNext(.neoVimStopped) + self.eventsSubject.onCompleted() + } + } + } + final func setAttr(with value: MessagePackValue) { guard let array = value.arrayValue else { self.bridgeLogger.error("Could not convert \(value)") diff --git a/NvimView/NvimView/NvimView.swift b/NvimView/NvimView/NvimView.swift index 99f49979..dee23d48 100644 --- a/NvimView/NvimView/NvimView.swift +++ b/NvimView/NvimView/NvimView.swift @@ -311,6 +311,8 @@ public class NvimView: NSView, case .rpcEventSubscribed: self?.rpcEventSubscribed() + case let .fatalError(value): + self?.bridgeHasFatalError(value) case .debug1: self?.debug1(nil) diff --git a/NvimView/NvimView/SharedTypes.h b/NvimView/NvimView/SharedTypes.h index 6f513b17..5a1ed5f1 100644 --- a/NvimView/NvimView/SharedTypes.h +++ b/NvimView/NvimView/SharedTypes.h @@ -46,9 +46,16 @@ typedef CF_ENUM(NSInteger, NvimServerMsgId) { NvimServerMsgIdAutoCommandEvent, NvimServerMsgIdRpcEventSubscribed, + NvimServerMsgIdFatalError, + NvimServerMsgIdDebug1, }; +typedef CF_ENUM(NSInteger, NvimServerFatalErrorCode) { + NvimServerFatalErrorCodeLocalPort = 1, + NvimServerFatalErrorCodeRemotePort, +}; + typedef CF_ENUM(NSInteger, NvimBridgeMsgId) { NvimBridgeMsgIdAgentReady = 0, NvimBridgeMsgIdReadyForRpcEvents, diff --git a/NvimView/NvimView/UiBridge.swift b/NvimView/NvimView/UiBridge.swift index 5499db8f..6ada1659 100644 --- a/NvimView/NvimView/UiBridge.swift +++ b/NvimView/NvimView/UiBridge.swift @@ -37,6 +37,7 @@ class UiBridge { case autoCommandEvent(MessagePackValue) case highlightAttrs(MessagePackValue) case rpcEventSubscribed + case fatalError(MessagePackValue?) case debug1 case unknown } @@ -255,6 +256,9 @@ class UiBridge { case .rpcEventSubscribed: self.streamSubject.onNext(.rpcEventSubscribed) + case .fatalError: + self.streamSubject.onNext(.fatalError(MessagePackUtils.value(from: data))) + } }