fix: fixes for shell/Terminal issues and CPU burn
This commit is contained in:
@@ -20,6 +20,7 @@ struct TermCell {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static constexpr int TERM_MAX_SCROLLBACK = 500;
|
static constexpr int TERM_MAX_SCROLLBACK = 500;
|
||||||
|
static constexpr int TERM_MAX_READS_PER_POLL = 8;
|
||||||
|
|
||||||
struct TerminalState {
|
struct TerminalState {
|
||||||
TermCell* cells;
|
TermCell* cells;
|
||||||
@@ -716,8 +717,8 @@ static inline void terminal_handle_key(TerminalState* t, const Montauk::KeyEvent
|
|||||||
static inline bool terminal_poll(TerminalState* t) {
|
static inline bool terminal_poll(TerminalState* t) {
|
||||||
if (t->child_pid <= 0) return false;
|
if (t->child_pid <= 0) return false;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
// Drain all available data so large output renders in one frame
|
// Drain a bounded amount per frame so window close/input events stay responsive.
|
||||||
for (;;) {
|
for (int reads = 0; reads < TERM_MAX_READS_PER_POLL; reads++) {
|
||||||
int n = montauk::childio_read(t->child_pid, buf, sizeof(buf));
|
int n = montauk::childio_read(t->child_pid, buf, sizeof(buf));
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
terminal_feed(t, buf, n);
|
terminal_feed(t, buf, n);
|
||||||
|
|||||||
@@ -233,11 +233,14 @@ static int window_visible_rows() {
|
|||||||
return mtk::table_visible_rows(window_table_layout());
|
return mtk::table_visible_rows(window_table_layout());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool process_state_alive(uint8_t state) {
|
||||||
|
return state == 1 || state == 2 || state == 3;
|
||||||
|
}
|
||||||
|
|
||||||
static int live_process_count() {
|
static int live_process_count() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int i = 0; i < g_pm.proc_count; i++) {
|
for (int i = 0; i < g_pm.proc_count; i++) {
|
||||||
uint8_t state = g_pm.procs[i].state;
|
if (process_state_alive(g_pm.procs[i].state))
|
||||||
if (state == 1 || state == 2 || state == 3)
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
@@ -246,13 +249,24 @@ static int live_process_count() {
|
|||||||
static uint64_t total_process_heap() {
|
static uint64_t total_process_heap() {
|
||||||
uint64_t total = 0;
|
uint64_t total = 0;
|
||||||
for (int i = 0; i < g_pm.proc_count; i++) {
|
for (int i = 0; i < g_pm.proc_count; i++) {
|
||||||
uint8_t state = g_pm.procs[i].state;
|
if (process_state_alive(g_pm.procs[i].state))
|
||||||
if (state == 1 || state == 2 || state == 3)
|
|
||||||
total += g_pm.procs[i].heapUsed;
|
total += g_pm.procs[i].heapUsed;
|
||||||
}
|
}
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void collect_descendant_pids(int parent_pid, int* pids, int* count, int max_count) {
|
||||||
|
for (int i = 0; i < g_pm.proc_count; i++) {
|
||||||
|
if (!process_state_alive(g_pm.procs[i].state)) continue;
|
||||||
|
if (g_pm.procs[i].parentPid != parent_pid) continue;
|
||||||
|
|
||||||
|
int child_pid = g_pm.procs[i].pid;
|
||||||
|
collect_descendant_pids(child_pid, pids, count, max_count);
|
||||||
|
if (*count < max_count)
|
||||||
|
pids[(*count)++] = child_pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int find_prev_cpu_snapshot(int pid) {
|
static int find_prev_cpu_snapshot(int pid) {
|
||||||
for (int i = 0; i < g_pm.prev_cpu_count; i++) {
|
for (int i = 0; i < g_pm.prev_cpu_count; i++) {
|
||||||
if (g_pm.prev_cpu[i].pid == pid)
|
if (g_pm.prev_cpu[i].pid == pid)
|
||||||
@@ -390,7 +404,15 @@ static void kill_selected() {
|
|||||||
if (!can_kill_selected())
|
if (!can_kill_selected())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
montauk::kill(g_pm.procs[g_pm.selected].pid);
|
int root_pid = g_pm.procs[g_pm.selected].pid;
|
||||||
|
int descendants[PM_MAX_PROCS];
|
||||||
|
int descendant_count = 0;
|
||||||
|
collect_descendant_pids(root_pid, descendants, &descendant_count, PM_MAX_PROCS);
|
||||||
|
|
||||||
|
for (int i = 0; i < descendant_count; i++)
|
||||||
|
montauk::kill(descendants[i]);
|
||||||
|
|
||||||
|
montauk::kill(root_pid);
|
||||||
refresh_state(true);
|
refresh_state(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -352,6 +352,25 @@ static constexpr uint8_t SC_DOWN = 0x50;
|
|||||||
static constexpr uint8_t SC_LEFT = 0x4B;
|
static constexpr uint8_t SC_LEFT = 0x4B;
|
||||||
static constexpr uint8_t SC_RIGHT = 0x4D;
|
static constexpr uint8_t SC_RIGHT = 0x4D;
|
||||||
|
|
||||||
|
static bool empty_key_event(const Montauk::KeyEvent& ev) {
|
||||||
|
return ev.scancode == 0 && ev.ascii == 0 && !ev.pressed &&
|
||||||
|
!ev.shift && !ev.ctrl && !ev.alt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wait_key_event(Montauk::KeyEvent* out) {
|
||||||
|
if (!out) return;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
montauk::getkey(out);
|
||||||
|
if (!empty_key_event(*out))
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint64_t serial = montauk::input_wait(0, 0);
|
||||||
|
if (!montauk::is_key_available())
|
||||||
|
montauk::input_wait(serial, ~0ULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---- Entry point ----
|
// ---- Entry point ----
|
||||||
|
|
||||||
extern "C" void _start() {
|
extern "C" void _start() {
|
||||||
@@ -380,13 +399,8 @@ extern "C" void _start() {
|
|||||||
prompt();
|
prompt();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!montauk::is_key_available()) {
|
|
||||||
montauk::yield();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Montauk::KeyEvent ev;
|
Montauk::KeyEvent ev;
|
||||||
montauk::getkey(&ev);
|
wait_key_event(&ev);
|
||||||
|
|
||||||
if (!ev.pressed) continue;
|
if (!ev.pressed) continue;
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ static bool g_should_exit = false;
|
|||||||
static bool g_force_redraw = true;
|
static bool g_force_redraw = true;
|
||||||
static int g_last_win_w = 0;
|
static int g_last_win_w = 0;
|
||||||
static int g_last_win_h = 0;
|
static int g_last_win_h = 0;
|
||||||
|
static Montauk::ProcInfo g_kill_procs[256];
|
||||||
|
static int g_kill_pids[256];
|
||||||
|
static int g_kill_pid_count = 0;
|
||||||
|
|
||||||
static bool left_pressed(const Montauk::WinEvent& ev) {
|
static bool left_pressed(const Montauk::WinEvent& ev) {
|
||||||
return (ev.mouse.buttons & 1) && !(ev.mouse.prev_buttons & 1);
|
return (ev.mouse.buttons & 1) && !(ev.mouse.prev_buttons & 1);
|
||||||
@@ -54,9 +57,40 @@ static void term_request_redraw() {
|
|||||||
g_force_redraw = true;
|
g_force_redraw = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool term_proc_alive(uint8_t state) {
|
||||||
|
return state == 1 || state == 2 || state == 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void term_collect_child_pids(int parent_pid, int proc_count) {
|
||||||
|
for (int i = 0; i < proc_count; i++) {
|
||||||
|
if (!term_proc_alive(g_kill_procs[i].state)) continue;
|
||||||
|
if (g_kill_procs[i].parentPid != parent_pid) continue;
|
||||||
|
|
||||||
|
int child_pid = g_kill_procs[i].pid;
|
||||||
|
term_collect_child_pids(child_pid, proc_count);
|
||||||
|
if (g_kill_pid_count < (int)(sizeof(g_kill_pids) / sizeof(g_kill_pids[0])))
|
||||||
|
g_kill_pids[g_kill_pid_count++] = child_pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void term_kill_process_tree(int root_pid) {
|
||||||
|
if (root_pid <= 0) return;
|
||||||
|
|
||||||
|
g_kill_pid_count = 0;
|
||||||
|
int proc_count = montauk::proclist(g_kill_procs,
|
||||||
|
(int)(sizeof(g_kill_procs) / sizeof(g_kill_procs[0])));
|
||||||
|
if (proc_count > 0)
|
||||||
|
term_collect_child_pids(root_pid, proc_count);
|
||||||
|
|
||||||
|
for (int i = 0; i < g_kill_pid_count; i++)
|
||||||
|
montauk::kill(g_kill_pids[i]);
|
||||||
|
|
||||||
|
montauk::kill(root_pid);
|
||||||
|
}
|
||||||
|
|
||||||
static void term_free_tab(TerminalState* ts) {
|
static void term_free_tab(TerminalState* ts) {
|
||||||
if (!ts) return;
|
if (!ts) return;
|
||||||
if (ts->child_pid > 0) montauk::kill(ts->child_pid);
|
if (ts->child_pid > 0) term_kill_process_tree(ts->child_pid);
|
||||||
if (ts->cells) montauk::free(ts->cells);
|
if (ts->cells) montauk::free(ts->cells);
|
||||||
if (ts->alt_cells) montauk::free(ts->alt_cells);
|
if (ts->alt_cells) montauk::free(ts->alt_cells);
|
||||||
montauk::mfree(ts);
|
montauk::mfree(ts);
|
||||||
@@ -367,9 +401,7 @@ extern "C" void _start() {
|
|||||||
g_win.present();
|
g_win.present();
|
||||||
|
|
||||||
while (!g_should_exit) {
|
while (!g_should_exit) {
|
||||||
bool redraw = term_poll_tabs();
|
bool redraw = false;
|
||||||
if (g_should_exit) break;
|
|
||||||
|
|
||||||
Montauk::WinEvent ev;
|
Montauk::WinEvent ev;
|
||||||
bool quit = false;
|
bool quit = false;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
@@ -400,6 +432,9 @@ extern "C" void _start() {
|
|||||||
|
|
||||||
if (r < 0 || quit) break;
|
if (r < 0 || quit) break;
|
||||||
|
|
||||||
|
redraw |= term_poll_tabs();
|
||||||
|
if (g_should_exit) break;
|
||||||
|
|
||||||
if (redraw && term_render())
|
if (redraw && term_render())
|
||||||
g_win.present();
|
g_win.present();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user