Skip to content

Commit 301fa2d

Browse files
better shutdown via ipc
1 parent 800249e commit 301fa2d

5 files changed

Lines changed: 98 additions & 13 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ollieos",
3-
"version": "2.5.3",
3+
"version": "2.5.4",
44
"description": "",
55
"main": "server.js",
66
"scripts": {

src/kernel/index.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,30 @@ export class Kernel {
639639
});
640640
}
641641

642+
power_off() {
643+
// dispose of all terminals of any remaining processes, including the kernel terminal
644+
const proc_mgr = this.get_process_manager();
645+
const pids = proc_mgr.list_pids();
646+
647+
for (const pid of pids) {
648+
const proc = proc_mgr.get_process(pid);
649+
proc.terminal.dispose();
650+
}
651+
652+
this.#term.dispose();
653+
654+
proc_mgr.dispose_all();
655+
}
656+
657+
reboot() {
658+
this.power_off();
659+
660+
if (typeof window !== "undefined") {
661+
// TODO: more formal reboot here, calling boot again with clean state somehow
662+
window.location.reload();
663+
}
664+
}
665+
642666
constructor(term: AbstractTerminal, fs: AbstractFileSystem, prog_registry?: ProgramRegistry, sound_registry?: SoundRegistry, wm?: AbstractWindowManager, net_manager?: AbstractNetworkManager) {
643667
this.#term = term;
644668
this.#fs = fs;

src/programs/core/ignition/index.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,63 @@ export default {
183183
}
184184
}
185185
break;
186+
case "power": {
187+
const power_msg = payload as IgnitionIPCPowerMessage;
188+
switch (power_msg.action) {
189+
case "shutdown": {
190+
ipc.channel_send(channel_id, process.pid, {
191+
type: "response",
192+
message: power_msg.hard ? "Hard shutdown initiated." : "Shutdown initiated."
193+
});
194+
195+
// TODO: stop services in reverse order
196+
197+
// kill all processes except for init in reverse order of creation
198+
// TODO: polite shutdown signal first (need to add) then force kill after timeout (or instantly based on force flag)
199+
const proc_mgr = kernel.get_process_manager();
200+
const pids = proc_mgr.list_pids().reverse();
201+
for (const pid of pids) {
202+
if (pid !== process.pid) {
203+
const proc = proc_mgr.get_process(pid);
204+
if (proc) {
205+
proc.kill();
206+
}
207+
}
208+
}
209+
210+
kernel.power_off();
211+
break;
212+
}
213+
case "reboot": {
214+
ipc.channel_send(channel_id, process.pid, {
215+
type: "response",
216+
message: power_msg.hard ? "Hard reboot initiated." : "Reboot initiated."
217+
});
218+
219+
// TODO: stop services in reverse order
220+
221+
// kill all processes except for init in reverse order of creation
222+
const proc_mgr = kernel.get_process_manager();
223+
const pids = proc_mgr.list_pids().reverse();
224+
for (const pid of pids) {
225+
if (pid !== process.pid) {
226+
const proc = proc_mgr.get_process(pid);
227+
if (proc) {
228+
proc.kill();
229+
}
230+
}
231+
}
232+
233+
kernel.reboot();
234+
break;
235+
}
236+
default:
237+
ipc.channel_send(channel_id, process.pid, {
238+
type: "error",
239+
message: `Unknown power action: ${power_msg.action}`
240+
});
241+
}
242+
}
186243
default:
187244
ipc.channel_send(channel_id, process.pid, {
188245
type: "error",

src/programs/shutdown.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export default {
1616
// TODO: completion
1717
main: async (data) => {
1818
// extract from data to make code less verbose
19-
const { kernel, shell, args, term } = data;
19+
const { kernel, shell, args, term, process } = data;
2020

2121
// extract from ANSI to make code less verbose
2222
const { FG, STYLE } = ANSI;
@@ -68,15 +68,20 @@ export default {
6868
term.writeln(`${FG.red}Shutting down...${STYLE.reset_all}`);
6969
}
7070

71-
setTimeout(() => {
72-
if (restart) {
73-
window.location.reload();
74-
} else {
75-
// TODO: need to dispose ALL terminals. def easier to manage in igntion but could make a kernel.dispose() method
76-
// TODO: send kill signal to all processes to allow them to clean up before shutdown
77-
// TODO: this behaviour should be moved to either kernel or ignition
78-
term.dispose();
71+
process.create_timeout(() => {
72+
// talk to ignition over ipc
73+
const ipc = kernel.get_ipc();
74+
const channel_id = ipc.create_channel("init");
75+
76+
if (!channel_id) {
77+
term.writeln(`${FG.red}Failed to communicate with ignition.${STYLE.reset_all}`);
78+
return;
7979
}
80+
81+
ipc.channel_send(channel_id, {
82+
type: "power",
83+
action: restart ? "reboot" : "shutdown",
84+
});
8085
}, time);
8186

8287
// hang the terminal until it is shut down or restarted (dont allow any more commands)
@@ -85,4 +90,3 @@ export default {
8590
}
8691
} as Program;
8792

88-
// TODO: move this to talk to ignition to perform a soft (or hard) shutdown via IPC

0 commit comments

Comments
 (0)