Skip to content

Commit 9faefad

Browse files
committed
add: ipc: groundwork for graceful exits
1 parent 4c1ff34 commit 9faefad

File tree

5 files changed

+52
-12
lines changed

5 files changed

+52
-12
lines changed

src/components/ipc/shared.nim

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,16 @@ type
270270
## feJSWebSocketEvent
271271
feJSWebSocketEvent
272272

273+
## feShutdown
274+
## The IPC server sends this to a process when it needs to close. The process doesn't need to actually close during the scenarios below:
275+
## - the renderer is busy laying out content during the exit
276+
## - the JavaScript runtime is executing an unrecoverable loop
277+
## - the HTML/CSS parser is deadlocked due to a bug
278+
## - the network process is fetching some content
279+
##
280+
## It's more of a hint to start cleaning up, as the IPC server will soonly after call `kill(2)` on the process.
281+
feGoodbye
282+
273283
DataTransferRequest* = ref object
274284
kind: FerusMagic = feDataTransferRequest
275285

@@ -281,11 +291,14 @@ type
281291

282292
success*: bool
283293
data*: string
284-
294+
285295
# TODO: might wanna move these into their own file
286296
HandshakePacket* = ref object
287297
kind: FerusMagic = feHandshake
288298
process*: FerusProcess
299+
300+
GoodbyePacket* = object
301+
kind: FerusMagic = feGoodbye
289302

290303
ExitReason* = enum
291304
erUnknown ## Unhandled crash, most likely.

src/components/master/master.nim

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import std/[os, logging, osproc, strutils, options, base64, net, sets, terminal, tables]
1+
import std/[os, logging, osproc, strutils, options, base64, net, sets, terminal, posix, tables]
22
import ../../components/ipc/server/prelude
33
import jsony
44
import ./summon
@@ -408,6 +408,20 @@ proc onConsoleLog*(
408408
resetStyle,
409409
)
410410

411+
proc requestShutdown*(master: MasterProcess, process: FerusProcess) =
412+
info "Requesting shutdown for " & $process.kind & " process (PID " & $process.pid & ")"
413+
master.server.send(process.socket, GoodbyePacket())
414+
415+
proc cleanupAllProcesses*(master: MasterProcess) =
416+
for group in master.server.groups:
417+
for process in group:
418+
master.requestShutdown(process)
419+
420+
for group in master.server.groups:
421+
for process in group:
422+
if kill(process.pid.Pid, SIGKILL) != 0:
423+
error "An error occured whilst killing child process: " & $strerror(errno)
424+
411425
proc packetHandler*(
412426
master: MasterProcess, process: FerusProcess, kind: FerusMagic, data: string
413427
) =
@@ -493,6 +507,15 @@ proc packetHandler*(
493507
return
494508

495509
master.server.send(process.socket, &resp)
510+
of feRendererExit:
511+
if process.kind != Renderer:
512+
master.server.reportBadMessage(
513+
process,
514+
"Non-renderer process sent `feRendererExit` opcode",
515+
High
516+
)
517+
518+
debug "The renderer has shut down."
496519
else:
497520
warn "Unhandled IPC protocol magic: " & $kind
498521
return

src/components/renderer/core.nim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ proc close*(renderer: FerusRenderer) {.inline.} =
6262
info "Closing renderer."
6363

6464
destroy renderer.window
65+
renderer.ipc.send(RendererExit()) # tell the IPC server we're exiting.
6566
glfw.terminate()
6667

6768
proc setWindowTitle*(renderer: FerusRenderer, title: string) {.inline.} =

src/components/renderer/ipc.nim

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import std/base64
2-
3-
import ../../components/ipc/shared, vmath
4-
from ferusgfx import Scene
5-
import ferusgfx/displaylist
2+
import ../../components/ipc/shared
3+
import pkg/vmath
4+
from pkg/ferusgfx import Scene
5+
import pkg/ferusgfx/displaylist
66

77
import ../parsers/html/document
88

@@ -23,25 +23,28 @@ type
2323
of GIFNode:
2424
gifContent*: string
2525

26-
RendererMutationPacket* = ref object
26+
RendererMutationPacket* = object
2727
kind: FerusMagic = feRendererMutation
2828
list*: IPCDisplayList
2929

30-
RendererLoadFontPacket* = ref object
30+
RendererLoadFontPacket* = object
3131
kind: FerusMagic = feRendererLoadFont
3232
name*, content*, format*: string
3333

34-
RendererSetWindowTitle* = ref object
34+
RendererSetWindowTitle* = object
3535
kind: FerusMagic = feRendererSetWindowTitle
3636
title*: string
3737

38-
RendererRenderDocument* = ref object
38+
RendererRenderDocument* = object
3939
kind: FerusMagic = feRendererRenderDocument
4040
document*: HTMLDocument
4141

42-
RendererGotoURL* = ref object
42+
RendererGotoURL* = object
4343
kind: FerusMagic = feRendererGotoURL
4444
url*: string
45+
46+
RendererExit* = object
47+
kind: FerusMagic = feRendererExit
4548

4649
IPCDisplayList* = GDisplayList[Drawable] ## IPC display list
4750

src/components/renderer/process.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,5 +163,5 @@ proc renderProcessLogic*(client: var IPCClient, process: FerusProcess) {.inline.
163163
while not renderer.shouldClose:
164164
client.talk(renderer, process)
165165
renderer.tick()
166-
166+
167167
close renderer

0 commit comments

Comments
 (0)