mirror of
https://github.com/RGBCube/serenity
synced 2025-05-22 00:15:08 +00:00
Allow processes to go into a BeingInspected state (used by procfs.)
This ensures that the process won't get scheduled, and so inspecting it is safe and easy without blocking interrupts.
This commit is contained in:
parent
dfaa2b6b02
commit
52607aa086
3 changed files with 37 additions and 19 deletions
|
@ -27,8 +27,9 @@ ProcFileSystem::~ProcFileSystem()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer procfs$pid_fds(const Process& process)
|
ByteBuffer procfs$pid_fds(Process& process)
|
||||||
{
|
{
|
||||||
|
ProcessInspectionScope scope(process);
|
||||||
char* buffer;
|
char* buffer;
|
||||||
auto stringImpl = StringImpl::createUninitialized(process.number_of_open_file_descriptors() * 80, buffer);
|
auto stringImpl = StringImpl::createUninitialized(process.number_of_open_file_descriptors() * 80, buffer);
|
||||||
memset(buffer, 0, stringImpl->length());
|
memset(buffer, 0, stringImpl->length());
|
||||||
|
@ -43,9 +44,9 @@ ByteBuffer procfs$pid_fds(const Process& process)
|
||||||
return ByteBuffer::copy((byte*)buffer, ptr - buffer);
|
return ByteBuffer::copy((byte*)buffer, ptr - buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer procfs$pid_vm(const Process& process)
|
ByteBuffer procfs$pid_vm(Process& process)
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
ProcessInspectionScope scope(process);
|
||||||
char* buffer;
|
char* buffer;
|
||||||
auto stringImpl = StringImpl::createUninitialized(80 + process.regionCount() * 80 + 80 + process.subregionCount() * 80, buffer);
|
auto stringImpl = StringImpl::createUninitialized(80 + process.regionCount() * 80 + 80 + process.subregionCount() * 80, buffer);
|
||||||
memset(buffer, 0, stringImpl->length());
|
memset(buffer, 0, stringImpl->length());
|
||||||
|
@ -76,7 +77,7 @@ ByteBuffer procfs$pid_vm(const Process& process)
|
||||||
|
|
||||||
ByteBuffer procfs$pid_stack(Process& process)
|
ByteBuffer procfs$pid_stack(Process& process)
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
ProcessInspectionScope scope(process);
|
||||||
OtherProcessPagingScope pagingScope(process);
|
OtherProcessPagingScope pagingScope(process);
|
||||||
struct RecognizedSymbol {
|
struct RecognizedSymbol {
|
||||||
dword address;
|
dword address;
|
||||||
|
@ -108,11 +109,8 @@ ByteBuffer procfs$pid_stack(Process& process)
|
||||||
|
|
||||||
ByteBuffer procfs$pid_exe(Process& process)
|
ByteBuffer procfs$pid_exe(Process& process)
|
||||||
{
|
{
|
||||||
InodeIdentifier inode;
|
ProcessInspectionScope scope(process);
|
||||||
{
|
auto inode = process.executableInode();
|
||||||
InterruptDisabler disabler;
|
|
||||||
inode = process.executableInode();
|
|
||||||
}
|
|
||||||
return VirtualFileSystem::the().absolutePath(inode).toByteBuffer();
|
return VirtualFileSystem::the().absolutePath(inode).toByteBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,6 +199,7 @@ static const char* toString(Process::State state)
|
||||||
case Process::BlockedSleep: return "Sleep";
|
case Process::BlockedSleep: return "Sleep";
|
||||||
case Process::BlockedWait: return "Wait";
|
case Process::BlockedWait: return "Wait";
|
||||||
case Process::BlockedRead: return "Read";
|
case Process::BlockedRead: return "Read";
|
||||||
|
case Process::BeingInspected: return "Inspect";
|
||||||
}
|
}
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -533,7 +533,7 @@ void Process::sys$exit(int status)
|
||||||
kprintf("sys$exit: %s(%u) exit with status %d\n", name().characters(), pid(), status);
|
kprintf("sys$exit: %s(%u) exit with status %d\n", name().characters(), pid(), status);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setState(Exiting);
|
set_state(Exiting);
|
||||||
|
|
||||||
s_processes->remove(this);
|
s_processes->remove(this);
|
||||||
|
|
||||||
|
@ -553,7 +553,7 @@ void Process::murder(int signal)
|
||||||
{
|
{
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
bool wasCurrent = current == this;
|
bool wasCurrent = current == this;
|
||||||
setState(Exiting);
|
set_state(Exiting);
|
||||||
s_processes->remove(this);
|
s_processes->remove(this);
|
||||||
|
|
||||||
notify_waiters(m_pid, 0, signal);
|
notify_waiters(m_pid, 0, signal);
|
||||||
|
@ -579,7 +579,7 @@ void Process::processDidCrash(Process* crashedProcess)
|
||||||
HANG;
|
HANG;
|
||||||
}
|
}
|
||||||
|
|
||||||
crashedProcess->setState(Crashing);
|
crashedProcess->set_state(Crashing);
|
||||||
crashedProcess->dumpRegions();
|
crashedProcess->dumpRegions();
|
||||||
|
|
||||||
s_processes->remove(crashedProcess);
|
s_processes->remove(crashedProcess);
|
||||||
|
@ -741,11 +741,11 @@ static bool contextSwitch(Process* t)
|
||||||
// If the last process hasn't blocked (still marked as running),
|
// If the last process hasn't blocked (still marked as running),
|
||||||
// mark it as runnable for the next round.
|
// mark it as runnable for the next round.
|
||||||
if (current->state() == Process::Running)
|
if (current->state() == Process::Running)
|
||||||
current->setState(Process::Runnable);
|
current->set_state(Process::Runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
current = t;
|
current = t;
|
||||||
t->setState(Process::Running);
|
t->set_state(Process::Running);
|
||||||
|
|
||||||
if (!t->selector()) {
|
if (!t->selector()) {
|
||||||
t->setSelector(allocateGDTEntry());
|
t->setSelector(allocateGDTEntry());
|
||||||
|
@ -1074,7 +1074,7 @@ void Process::block(Process::State state)
|
||||||
{
|
{
|
||||||
ASSERT(current->state() == Process::Running);
|
ASSERT(current->state() == Process::Running);
|
||||||
system.nblocked++;
|
system.nblocked++;
|
||||||
current->setState(state);
|
current->set_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void block(Process::State state)
|
void block(Process::State state)
|
||||||
|
|
|
@ -30,9 +30,10 @@ public:
|
||||||
Terminated = 3,
|
Terminated = 3,
|
||||||
Crashing = 4,
|
Crashing = 4,
|
||||||
Exiting = 5,
|
Exiting = 5,
|
||||||
BlockedSleep = 6,
|
BeingInspected = 6,
|
||||||
BlockedWait = 7,
|
BlockedSleep = 7,
|
||||||
BlockedRead = 8,
|
BlockedWait = 8,
|
||||||
|
BlockedRead = 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RingLevel {
|
enum RingLevel {
|
||||||
|
@ -75,7 +76,7 @@ public:
|
||||||
void setTicksLeft(DWORD t) { m_ticksLeft = t; }
|
void setTicksLeft(DWORD t) { m_ticksLeft = t; }
|
||||||
|
|
||||||
void setSelector(WORD s) { m_farPtr.selector = s; }
|
void setSelector(WORD s) { m_farPtr.selector = s; }
|
||||||
void setState(State s) { m_state = s; }
|
void set_state(State s) { m_state = s; }
|
||||||
|
|
||||||
uid_t sys$getuid();
|
uid_t sys$getuid();
|
||||||
gid_t sys$getgid();
|
gid_t sys$getgid();
|
||||||
|
@ -203,6 +204,24 @@ private:
|
||||||
Vector<String> m_initialEnvironment;
|
Vector<String> m_initialEnvironment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ProcessInspectionScope {
|
||||||
|
public:
|
||||||
|
ProcessInspectionScope(Process& process)
|
||||||
|
: m_process(process)
|
||||||
|
, m_original_state(process.state())
|
||||||
|
{
|
||||||
|
m_process.set_state(Process::BeingInspected);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ProcessInspectionScope()
|
||||||
|
{
|
||||||
|
m_process.set_state(m_original_state);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Process& m_process;
|
||||||
|
Process::State m_original_state { Process::Invalid };
|
||||||
|
};
|
||||||
|
|
||||||
extern void yield();
|
extern void yield();
|
||||||
extern bool scheduleNewProcess();
|
extern bool scheduleNewProcess();
|
||||||
extern void switchNow();
|
extern void switchNow();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue