mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
SystemMonitor: Handle zombie processes properly
SystemMonitor had a bug in which it would crash in case there are zombie processes left in the system. The fix for this is to check if a process has no threads (which will indicate that the process is a zombie and is waiting to be reaped), and if that's the case, artificially create a thread row that is just enough to represent the zombie process.
This commit is contained in:
parent
dca56ce1cb
commit
e931b2ecd9
Notes:
sideshowbarker
2024-07-17 09:49:48 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/e931b2ecd9 Pull-request: https://github.com/SerenityOS/serenity/pull/18202 Issue: https://github.com/SerenityOS/serenity/issues/18200 Reviewed-by: https://github.com/ADKaster ✅ Reviewed-by: https://github.com/gmta
1 changed files with 64 additions and 29 deletions
|
@ -468,55 +468,90 @@ void ProcessModel::update()
|
|||
m_processes.append(make<Process>());
|
||||
process_state = &m_processes.last();
|
||||
}
|
||||
|
||||
auto add_thread_data = [&live_tids, this](int tid, Process& process_state, ThreadState state) {
|
||||
auto thread_data = m_threads.ensure(tid, [&] { return make_ref_counted<Thread>(process_state); });
|
||||
thread_data->previous_state = move(thread_data->current_state);
|
||||
thread_data->current_state = move(state);
|
||||
if (auto maybe_thread_index = process_state.threads.find_first_index(thread_data); maybe_thread_index.has_value()) {
|
||||
process_state.threads[maybe_thread_index.value()] = thread_data;
|
||||
} else {
|
||||
process_state.threads.append(thread_data);
|
||||
}
|
||||
live_tids.set(tid);
|
||||
};
|
||||
|
||||
(*process_state)->pid = process.pid;
|
||||
for (auto& thread : process.threads) {
|
||||
if (!process.threads.is_empty()) {
|
||||
for (auto& thread : process.threads) {
|
||||
ThreadState state(**process_state);
|
||||
state.tid = thread.tid;
|
||||
state.pid = process.pid;
|
||||
state.ppid = process.ppid;
|
||||
state.pgid = process.pgid;
|
||||
state.sid = process.sid;
|
||||
state.time_user = thread.time_user;
|
||||
state.time_kernel = thread.time_kernel;
|
||||
state.kernel = process.kernel;
|
||||
state.executable = process.executable;
|
||||
state.name = thread.name;
|
||||
state.command = read_command_line(process.pid);
|
||||
state.uid = process.uid;
|
||||
state.state = thread.state;
|
||||
state.user = process.username;
|
||||
state.pledge = process.pledge;
|
||||
state.veil = process.veil;
|
||||
state.cpu = thread.cpu;
|
||||
state.priority = thread.priority;
|
||||
state.amount_virtual = process.amount_virtual;
|
||||
state.amount_resident = process.amount_resident;
|
||||
state.amount_dirty_private = process.amount_dirty_private;
|
||||
state.amount_clean_inode = process.amount_clean_inode;
|
||||
state.amount_purgeable_volatile = process.amount_purgeable_volatile;
|
||||
state.amount_purgeable_nonvolatile = process.amount_purgeable_nonvolatile;
|
||||
state.syscall_count = thread.syscall_count;
|
||||
state.inode_faults = thread.inode_faults;
|
||||
state.zero_faults = thread.zero_faults;
|
||||
state.cow_faults = thread.cow_faults;
|
||||
state.unix_socket_read_bytes = thread.unix_socket_read_bytes;
|
||||
state.unix_socket_write_bytes = thread.unix_socket_write_bytes;
|
||||
state.ipv4_socket_read_bytes = thread.ipv4_socket_read_bytes;
|
||||
state.ipv4_socket_write_bytes = thread.ipv4_socket_write_bytes;
|
||||
state.file_read_bytes = thread.file_read_bytes;
|
||||
state.file_write_bytes = thread.file_write_bytes;
|
||||
state.cpu_percent = 0;
|
||||
|
||||
add_thread_data(thread.tid, **process_state, move(state));
|
||||
}
|
||||
} else {
|
||||
// FIXME: If there are no threads left in a process this is an indication
|
||||
// for a zombie process, so it should be handled differently - we add a mock thread
|
||||
// just to simulate a process with a single thread.
|
||||
// Find a way to untie the process representation from a main thread so we can
|
||||
// just represent a zombie process without creating a mock thread.
|
||||
ThreadState state(**process_state);
|
||||
state.tid = thread.tid;
|
||||
state.tid = process.pid;
|
||||
state.pid = process.pid;
|
||||
state.ppid = process.ppid;
|
||||
state.pgid = process.pgid;
|
||||
state.sid = process.sid;
|
||||
state.time_user = thread.time_user;
|
||||
state.time_kernel = thread.time_kernel;
|
||||
state.kernel = process.kernel;
|
||||
state.executable = process.executable;
|
||||
state.name = thread.name;
|
||||
state.name = process.name;
|
||||
state.command = read_command_line(process.pid);
|
||||
state.uid = process.uid;
|
||||
state.state = thread.state;
|
||||
state.state = "Zombie";
|
||||
state.user = process.username;
|
||||
state.pledge = process.pledge;
|
||||
state.veil = process.veil;
|
||||
state.cpu = thread.cpu;
|
||||
state.priority = thread.priority;
|
||||
state.amount_virtual = process.amount_virtual;
|
||||
state.amount_resident = process.amount_resident;
|
||||
state.amount_dirty_private = process.amount_dirty_private;
|
||||
state.amount_clean_inode = process.amount_clean_inode;
|
||||
state.amount_purgeable_volatile = process.amount_purgeable_volatile;
|
||||
state.amount_purgeable_nonvolatile = process.amount_purgeable_nonvolatile;
|
||||
state.syscall_count = thread.syscall_count;
|
||||
state.inode_faults = thread.inode_faults;
|
||||
state.zero_faults = thread.zero_faults;
|
||||
state.cow_faults = thread.cow_faults;
|
||||
state.unix_socket_read_bytes = thread.unix_socket_read_bytes;
|
||||
state.unix_socket_write_bytes = thread.unix_socket_write_bytes;
|
||||
state.ipv4_socket_read_bytes = thread.ipv4_socket_read_bytes;
|
||||
state.ipv4_socket_write_bytes = thread.ipv4_socket_write_bytes;
|
||||
state.file_read_bytes = thread.file_read_bytes;
|
||||
state.file_write_bytes = thread.file_write_bytes;
|
||||
state.cpu_percent = 0;
|
||||
|
||||
auto thread_data = m_threads.ensure(thread.tid, [&] { return make_ref_counted<Thread>(**process_state); });
|
||||
thread_data->previous_state = move(thread_data->current_state);
|
||||
thread_data->current_state = move(state);
|
||||
if (auto maybe_thread_index = (*process_state)->threads.find_first_index(thread_data); maybe_thread_index.has_value()) {
|
||||
(*process_state)->threads[maybe_thread_index.value()] = thread_data;
|
||||
} else {
|
||||
(*process_state)->threads.append(thread_data);
|
||||
}
|
||||
|
||||
live_tids.set(thread.tid);
|
||||
add_thread_data(process.pid, **process_state, move(state));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue