Skip to content

Commit e3a72d0

Browse files
authored
Fix displaying error dialog and logging errors (#1848)
1 parent dcf7297 commit e3a72d0

File tree

8 files changed

+156
-111
lines changed

8 files changed

+156
-111
lines changed

elixirkit/demo/rel/appkit/Sources/Demo/Demo.swift

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,37 @@ public struct Demo {
1212
}
1313

1414
class AppDelegate: NSObject, NSApplicationDelegate {
15-
private var window : NSWindow!
15+
private var window: NSWindow!
16+
private var button: NSButton!
1617

1718
func applicationDidFinishLaunching(_ aNotification: Notification) {
19+
button = NSButton(title: "Press me!", target: self, action: #selector(pressMe))
20+
button.isEnabled = false
21+
1822
ElixirKit.API.start(
1923
name: "demo",
24+
readyHandler: {
25+
// GUI updates need to happen on the main thread.
26+
DispatchQueue.main.sync {
27+
self.button.isEnabled = true
28+
}
29+
30+
ElixirKit.API.publish("log", "Hello from AppKit!")
31+
32+
ElixirKit.API.addObserver(queue: .main) { (name, data) in
33+
switch name {
34+
case "log":
35+
print("[client] " + data)
36+
default:
37+
fatalError("unknown event \(name)")
38+
}
39+
}
40+
},
2041
terminationHandler: { _ in
2142
NSApp.terminate(nil)
2243
}
2344
)
2445

25-
ElixirKit.API.publish("log", "Hello from AppKit!")
26-
27-
ElixirKit.API.addObserver(queue: .main) { (name, data) in
28-
switch name {
29-
case "log":
30-
print("[client] " + data)
31-
default:
32-
fatalError("unknown event \(name)")
33-
}
34-
}
35-
3646
let menuItemOne = NSMenuItem()
3747
menuItemOne.submenu = NSMenu(title: "Demo")
3848
menuItemOne.submenu?.items = [
@@ -48,8 +58,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
4858
defer: true)
4959
window.orderFrontRegardless()
5060
window.title = "Demo"
51-
52-
let button = NSButton(title: "Press me!", target: self, action: #selector(pressMe))
5361
window.contentView!.subviews.append(button)
5462

5563
NSApp.setActivationPolicy(.regular)

elixirkit/demo/rel/dotnet/Demo.cs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,27 @@ class Demo
22
{
33
public static void Main()
44
{
5-
ElixirKit.API.Start(name: "demo");
6-
ElixirKit.API.Publish("log", "Hello from C#!");
7-
8-
ElixirKit.API.Subscribe((name, data) =>
9-
{
10-
switch (name)
5+
ElixirKit.API.Start(
6+
name: "demo",
7+
ready: () =>
118
{
12-
case "log":
13-
Console.WriteLine($"[client] {data}");
14-
break;
9+
ElixirKit.API.Publish("log", "Hello from C#!");
10+
11+
ElixirKit.API.Subscribe((name, data) =>
12+
{
13+
switch (name)
14+
{
15+
case "log":
16+
Console.WriteLine($"[client] {data}");
17+
break;
1518

16-
default:
17-
throw new Exception($"unknown event {name}");
19+
default:
20+
throw new Exception($"unknown event {name}");
21+
}
22+
});
1823
}
19-
});
24+
);
2025

21-
ElixirKit.API.WaitForExit();
26+
System.Console.WriteLine($"{ElixirKit.API.WaitForExit()}");
2227
}
2328
}

elixirkit/demo/rel/swift/Sources/Demo/Demo.swift

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,21 @@ struct Demo {
1010
exit(signal)
1111
}
1212

13-
ElixirKit.API.start(name: "demo")
14-
ElixirKit.API.publish("log", "Hello from Swift!")
13+
ElixirKit.API.start(
14+
name: "demo",
15+
readyHandler: {
16+
ElixirKit.API.publish("log", "Hello from Swift!")
1517

16-
ElixirKit.API.addObserver(queue: .main) { (name, data) in
17-
switch name {
18-
case "log":
19-
print("[client] " + data)
20-
default:
21-
fatalError("unknown event \(name)")
18+
ElixirKit.API.addObserver(queue: .main) { (name, data) in
19+
switch name {
20+
case "log":
21+
print("[client] " + data)
22+
default:
23+
fatalError("unknown event \(name)")
24+
}
25+
}
2226
}
23-
}
27+
)
2428

2529
ElixirKit.API.waitUntilExit()
2630
}

elixirkit/demo/rel/winforms/Demo.cs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,36 @@ static void Main()
77
{
88
if (ElixirKit.API.IsMainInstance("com.example.Demo"))
99
{
10-
ElixirKit.API.Start(name: "demo", exited: (exitCode) =>
11-
{
12-
Application.Exit();
13-
});
10+
ElixirKit.API.Start(
11+
name: "demo",
12+
ready: () =>
13+
{
14+
ElixirKit.API.Publish("log", "Hello from Windows Forms!");
15+
16+
ElixirKit.API.Subscribe((name, data) =>
17+
{
18+
switch (name)
19+
{
20+
case "log":
21+
Console.WriteLine($"[client] {data}");
22+
break;
23+
24+
default:
25+
throw new Exception($"unknown event {name}");
26+
}
27+
});
28+
},
29+
exited: (exitCode) =>
30+
{
31+
Application.Exit();
32+
}
33+
);
1434

1535
Application.ApplicationExit += (sender, args) =>
1636
{
1737
ElixirKit.API.Stop();
1838
};
1939

20-
ElixirKit.API.Publish("log", "Hello from Windows Forms!");
21-
22-
ElixirKit.API.Subscribe((name, data) =>
23-
{
24-
switch (name)
25-
{
26-
case "log":
27-
Console.WriteLine($"[client] {data}");
28-
break;
29-
30-
default:
31-
throw new Exception($"unknown event {name}");
32-
}
33-
});
34-
3540
ApplicationConfiguration.Initialize();
3641
Application.Run(new DemoForm());
3742
}

elixirkit/elixirkit_dotnet/ElixirKit.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
namespace ElixirKit;
1212

13+
public delegate void ReadyHandler();
14+
1315
public delegate void ExitHandler(int ExitCode);
1416

1517
public delegate void EventHandler(string Name, string Data);
@@ -43,11 +45,11 @@ public static bool HasExited {
4345
}
4446
}
4547

46-
public static void Start(string name, ExitHandler? exited = null, string? logPath = null)
48+
public static void Start(string name, ReadyHandler ready, ExitHandler? exited = null, string? logPath = null)
4749
{
4850
ensureMainInstance();
4951

50-
release = new Release(name, exited, logPath);
52+
release = new Release(name, ready, exited, logPath);
5153

5254
if (mutex != null)
5355
{
@@ -136,7 +138,7 @@ internal bool HasExited {
136138
}
137139
}
138140

139-
public Release(string name, ExitHandler? exited = null, string? logPath = null)
141+
public Release(string name, ReadyHandler ready, ExitHandler? exited = null, string? logPath = null)
140142
{
141143
logger = new Logger(logPath);
142144
listener = new Listener();
@@ -187,8 +189,11 @@ public Release(string name, ExitHandler? exited = null, string? logPath = null)
187189
process.BeginOutputReadLine();
188190
process.BeginErrorReadLine();
189191

190-
var tcpClient = listener.TcpListener.AcceptTcpClient();
191-
client = new Client(tcpClient);
192+
Task.Run(() => {
193+
var tcpClient = listener.TcpListener.AcceptTcpClient();
194+
client = new Client(tcpClient);
195+
ready();
196+
});
192197
}
193198

194199
public void Send(string message)

elixirkit/elixirkit_swift/Sources/ElixirKit/ElixirKit.swift

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,25 @@ public class API {
1313
}
1414
}
1515

16-
public static func start(name: String, logPath: String? = nil, terminationHandler: ((Process) -> Void)? = nil) {
17-
release = Release(name: name, logPath: logPath, terminationHandler: terminationHandler)
16+
public static func start(
17+
name: String,
18+
logPath: String? = nil,
19+
readyHandler: @escaping () -> Void,
20+
terminationHandler: ((Process) -> Void)? = nil) {
21+
22+
release = Release(name: name, logPath: logPath, readyHandler: readyHandler, terminationHandler: terminationHandler)
1823
}
1924

2025
public static func publish(_ name: String, _ data: String) {
21-
release?.publish(name, data)
26+
release!.publish(name, data)
2227
}
2328

2429
public static func stop() {
25-
release?.stop();
30+
release!.stop();
2631
}
2732

2833
public static func waitUntilExit() {
29-
release?.waitUntilExit();
34+
release!.waitUntilExit();
3035
}
3136

3237
public static func addObserver(queue: OperationQueue?, using: @escaping (((String, String)) -> Void)) {
@@ -42,6 +47,7 @@ private class Release {
4247
let logger: Logger
4348
let listener: NWListener
4449
var connection: Connection?
50+
let readyHandler: () -> Void
4551
let semaphore = DispatchSemaphore(value: 0)
4652

4753
var isRunning: Bool {
@@ -50,7 +56,13 @@ private class Release {
5056
}
5157
}
5258

53-
init(name: String, logPath: String? = nil, terminationHandler: ((Process) -> Void)? = nil) {
59+
init(
60+
name: String,
61+
logPath: String? = nil,
62+
readyHandler: @escaping () -> Void,
63+
terminationHandler: ((Process) -> Void)? = nil) {
64+
65+
self.readyHandler = readyHandler
5466
logger = Logger(logPath: logPath)
5567
listener = try! NWListener(using: .tcp, on: .any)
5668

@@ -77,7 +89,7 @@ private class Release {
7789
listener.newConnectionHandler = didAccept(conn:)
7890
listener.start(queue: .global())
7991

80-
let seconds = 15
92+
let seconds = 5
8193
let timeout = DispatchTime.now() + DispatchTimeInterval.seconds(seconds)
8294

8395
if semaphore.wait(timeout: timeout) == .timedOut {
@@ -86,7 +98,7 @@ private class Release {
8698
}
8799

88100
public func stop() {
89-
connection!.cancel()
101+
connection?.cancel()
90102
listener.cancel()
91103
waitUntilExit()
92104
}
@@ -117,11 +129,12 @@ private class Release {
117129
env["ELIXIRKIT_PORT"] = port
118130
process.environment = env
119131
try! process.run()
132+
semaphore.signal()
120133
}
121134

122135
private func didAccept(conn: NWConnection) {
123136
self.connection = Connection(conn: conn, logger: logger)
124-
semaphore.signal()
137+
readyHandler()
125138
}
126139
}
127140

rel/app/macos/Sources/Livebook/Livebook.swift

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,35 +21,40 @@ class AppDelegate: NSObject, NSApplicationDelegate {
2121
func applicationDidFinishLaunching(_ aNotification: Notification) {
2222
logPath = "\(NSHomeDirectory())/Library/Logs/Livebook.log"
2323

24-
ElixirKit.API.start(name: "app", logPath: logPath) { process in
25-
if process.terminationStatus != 0 {
26-
DispatchQueue.main.sync {
27-
let alert = NSAlert()
28-
alert.alertStyle = .critical
29-
alert.messageText = "Livebook exited with error status \(process.terminationStatus)"
30-
alert.addButton(withTitle: "Dismiss")
31-
alert.addButton(withTitle: "View Logs")
32-
33-
switch alert.runModal() {
34-
case .alertSecondButtonReturn:
35-
self.viewLogs()
36-
default:
37-
()
24+
ElixirKit.API.start(
25+
name: "app",
26+
logPath: logPath,
27+
readyHandler: {
28+
if (self.initialURLs == []) {
29+
ElixirKit.API.publish("open", "")
30+
}
31+
else {
32+
for url in self.initialURLs {
33+
ElixirKit.API.publish("open", url.absoluteString)
34+
}
35+
}
36+
},
37+
terminationHandler: { process in
38+
if process.terminationStatus != 0 {
39+
DispatchQueue.main.sync {
40+
let alert = NSAlert()
41+
alert.alertStyle = .critical
42+
alert.messageText = "Livebook exited with error status \(process.terminationStatus)"
43+
alert.addButton(withTitle: "Dismiss")
44+
alert.addButton(withTitle: "View Logs")
45+
46+
switch alert.runModal() {
47+
case .alertSecondButtonReturn:
48+
self.viewLogs()
49+
default:
50+
()
51+
}
3852
}
3953
}
40-
}
41-
42-
NSApp.terminate(nil)
43-
}
4454

45-
if (self.initialURLs == []) {
46-
ElixirKit.API.publish("open", "")
47-
}
48-
else {
49-
for url in self.initialURLs {
50-
ElixirKit.API.publish("open", url.absoluteString)
55+
NSApp.terminate(nil)
5156
}
52-
}
57+
)
5358

5459
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
5560
let button = statusItem.button!
@@ -81,7 +86,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
8186
fatalError("unknown event \(name)")
8287
}
8388
}
84-
8589
}
8690

8791
func applicationWillTerminate(_ aNotification: Notification) {

0 commit comments

Comments
 (0)