-/*
+/* $Id: kill.c,v 1.51 2002/03/05 11:33:12 ekohl Exp $
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ps/kill.c
#include <internal/ke.h>
#include <internal/mm.h>
#include <internal/ob.h>
+#include <internal/port.h>
+#include <internal/pool.h>
#define NDEBUG
#include <internal/debug.h>
extern ULONG PiNrThreads;
extern ULONG PiNrRunnableThreads;
extern KSPIN_LOCK PiThreadListLock;
+extern LIST_ENTRY PiThreadListHead;
+extern KSPIN_LOCK PiApcLock;
+
+VOID PsTerminateCurrentThread(NTSTATUS ExitStatus);
+
+#define TAG_TERMINATE_APC TAG('T', 'A', 'P', 'C')
/* FUNCTIONS *****************************************************************/
-VOID PsTerminateCurrentThread(NTSTATUS ExitStatus)
+VOID
+PiTerminateProcessThreads(PEPROCESS Process,
+ NTSTATUS ExitStatus)
+{
+ KIRQL oldlvl;
+ PLIST_ENTRY current_entry;
+ PETHREAD current;
+
+ DPRINT("PiTerminateProcessThreads(Process %x, ExitStatus %x)\n",
+ Process, ExitStatus);
+
+ KeAcquireSpinLock(&PiThreadListLock, &oldlvl);
+
+ current_entry = Process->ThreadListHead.Flink;
+ while (current_entry != &Process->ThreadListHead)
+ {
+ current = CONTAINING_RECORD(current_entry, ETHREAD,
+ Tcb.ProcessThreadListEntry);
+ if (current != PsGetCurrentThread() &&
+ current->DeadThread == 0)
+ {
+ DPRINT("Terminating %x, current thread: %x, "
+ "thread's process: %x\n", current, PsGetCurrentThread(),
+ current->ThreadsProcess);
+ KeReleaseSpinLock(&PiThreadListLock, oldlvl);
+ PsTerminateOtherThread(current, ExitStatus);
+ KeAcquireSpinLock(&PiThreadListLock, &oldlvl);
+ current_entry = Process->ThreadListHead.Flink;
+ }
+ else
+ {
+ current_entry = current_entry->Flink;
+ }
+ }
+ KeReleaseSpinLock(&PiThreadListLock, oldlvl);
+ DPRINT("Finished PiTerminateProcessThreads()\n");
+}
+
+VOID
+PsReapThreads(VOID)
+{
+ PLIST_ENTRY current_entry;
+ PETHREAD current;
+ KIRQL oldIrql;
+
+// DPRINT1("PsReapThreads()\n");
+
+ KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
+
+ current_entry = PiThreadListHead.Flink;
+
+ while (current_entry != &PiThreadListHead)
+ {
+ current = CONTAINING_RECORD(current_entry, ETHREAD,
+ Tcb.ThreadListEntry);
+
+ current_entry = current_entry->Flink;
+
+ if (current->Tcb.State == THREAD_STATE_TERMINATED_1)
+ {
+ PEPROCESS Process = current->ThreadsProcess;
+ NTSTATUS Status = current->ExitStatus;
+
+ DPRINT("PsProcessType %x\n", PsProcessType);
+ DPRINT("Reaping thread %x\n", current);
+ DPRINT("Pointer count %d\n", ObGetObjectPointerCount(Process));
+ current->Tcb.State = THREAD_STATE_TERMINATED_2;
+ RemoveEntryList(¤t->Tcb.ProcessThreadListEntry);
+ if (IsListEmpty(&Process->ThreadListHead))
+ {
+ DPRINT("Last thread terminated, terminating process\n");
+ KeReleaseSpinLock( &PiThreadListLock, oldIrql );
+ PiTerminateProcess(Process, Status);
+ KeAcquireSpinLock( &PiThreadListLock, &oldIrql );
+ }
+ DPRINT("Pointer count %d\n", ObGetObjectPointerCount(Process));
+ KeReleaseSpinLock(&PiThreadListLock, oldIrql);
+ ObDereferenceObject(current);
+ KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
+ current_entry = PiThreadListHead.Flink;
+ }
+ }
+ KeReleaseSpinLock(&PiThreadListLock, oldIrql);
+}
+
+VOID
+PsTerminateCurrentThread(NTSTATUS ExitStatus)
/*
* FUNCTION: Terminates the current thread
*/
{
- KIRQL oldlvl;
+ KIRQL oldIrql;
PETHREAD CurrentThread;
-
- PiNrThreads--;
+ PKTHREAD Thread;
+ PLIST_ENTRY current_entry;
+ PKMUTANT Mutant;
CurrentThread = PsGetCurrentThread();
- CurrentThread->ExitStatus = ExitStatus;
-
DPRINT("terminating %x\n",CurrentThread);
- ObDereferenceObject(CurrentThread->ThreadsProcess);
- CurrentThread->ThreadsProcess = NULL;
- KeRaiseIrql(DISPATCH_LEVEL,&oldlvl);
+ KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
- ObDereferenceObject(CurrentThread);
- DPRINT("ObGetReferenceCount(CurrentThread) %d\n",
- ObGetReferenceCount(CurrentThread));
+ CurrentThread->ExitStatus = ExitStatus;
+ Thread = KeGetCurrentThread();
+ KeCancelTimer(&Thread->Timer);
+ KeReleaseSpinLock(&PiThreadListLock, oldIrql);
+
+ /* abandon all owned mutants */
+ current_entry = Thread->MutantListHead.Flink;
+ while (current_entry != &Thread->MutantListHead)
+ {
+ Mutant = CONTAINING_RECORD(current_entry, KMUTANT,
+ MutantListEntry);
+ KeReleaseMutant(Mutant,
+ MUTANT_INCREMENT,
+ TRUE,
+ FALSE);
+ current_entry = Thread->MutantListHead.Flink;
+ }
+ KeAcquireDispatcherDatabaseLock(FALSE);
CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE;
KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader);
-
- PsDispatchThread(THREAD_STATE_TERMINATED);
+ KeReleaseDispatcherDatabaseLock(FALSE);
+
+ KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
+ PsDispatchThreadNoLock(THREAD_STATE_TERMINATED_1);
KeBugCheck(0);
}
-VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus)
+VOID STDCALL
+PiTerminateThreadRundownRoutine(PKAPC Apc)
+{
+ ExFreePool(Apc);
+}
+
+VOID STDCALL
+PiTerminateThreadKernelRoutine(PKAPC Apc,
+ PKNORMAL_ROUTINE* NormalRoutine,
+ PVOID* NormalContext,
+ PVOID* SystemArgument1,
+ PVOID* SystemArguemnt2)
+{
+ ExFreePool(Apc);
+}
+
+VOID STDCALL
+PiTerminateThreadNormalRoutine(PVOID NormalContext,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2)
+{
+ PsTerminateCurrentThread(PsGetCurrentThread()->ExitStatus);
+}
+
+VOID
+PsTerminateOtherThread(PETHREAD Thread,
+ NTSTATUS ExitStatus)
/*
- * FUNCTION: Terminate a thread when calling from that thread's context
+ * FUNCTION: Terminate a thread when calling from another thread's context
+ * NOTES: This function must be called with PiThreadListLock held
*/
{
- KIRQL oldIrql;
+ PKAPC Apc;
+
+ DPRINT("PsTerminateOtherThread(Thread %x, ExitStatus %x)\n",
+ Thread, ExitStatus);
+
+ Thread->DeadThread = 1;
+ Thread->ExitStatus = ExitStatus;
+ Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_TERMINATE_APC);
+ KeInitializeApc(Apc,
+ &Thread->Tcb,
+ 0,
+ PiTerminateThreadKernelRoutine,
+ PiTerminateThreadRundownRoutine,
+ PiTerminateThreadNormalRoutine,
+ KernelMode,
+ NULL);
+ KeInsertQueueApc(Apc,
+ NULL,
+ NULL,
+ KernelMode);
+}
+
+NTSTATUS STDCALL
+PiTerminateProcess(PEPROCESS Process,
+ NTSTATUS ExitStatus)
+{
+ DPRINT("PiTerminateProcess(Process %x, ExitStatus %x) PC %d HC %d\n",
+ Process, ExitStatus, ObGetObjectPointerCount(Process),
+ ObGetObjectHandleCount(Process));
- KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
- PiNrThreads--;
- if (Thread->Tcb.State == THREAD_STATE_RUNNABLE)
+ if (InterlockedExchange((PLONG)&Process->Pcb.State,
+ PROCESS_STATE_TERMINATED) ==
+ PROCESS_STATE_TERMINATED)
{
- PiNrRunnableThreads--;
- RemoveEntryList(&Thread->Tcb.QueueListEntry);
+ return(STATUS_SUCCESS);
}
- Thread->Tcb.State = THREAD_STATE_TERMINATED;
- Thread->Tcb.DispatcherHeader.SignalState = TRUE;
- KeDispatcherObjectWake(&Thread->Tcb.DispatcherHeader);
- ObDereferenceObject(Thread->ThreadsProcess);
- ObDereferenceObject(Thread);
- Thread->ThreadsProcess = NULL;
- KeReleaseSpinLock(&PiThreadListLock, oldIrql);
+ KeAttachProcess( Process );
+ ObCloseAllHandles(Process);
+ KeDetachProcess();
+ KeAcquireDispatcherDatabaseLock(FALSE);
+ Process->Pcb.DispatcherHeader.SignalState = TRUE;
+ KeDispatcherObjectWake(&Process->Pcb.DispatcherHeader);
+ KeReleaseDispatcherDatabaseLock(FALSE);
+ return(STATUS_SUCCESS);
}
-
-NTSTATUS STDCALL NtTerminateProcess(IN HANDLE ProcessHandle,
- IN NTSTATUS ExitStatus)
+NTSTATUS STDCALL
+NtTerminateProcess(IN HANDLE ProcessHandle,
+ IN NTSTATUS ExitStatus)
{
NTSTATUS Status;
PEPROCESS Process;
- KIRQL oldlvl;
DPRINT("NtTerminateProcess(ProcessHandle %x, ExitStatus %x)\n",
- ProcessHandle, ExitStatus);
+ ProcessHandle, ExitStatus);
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_TERMINATE,
UserMode,
(PVOID*)&Process,
NULL);
- if (Status != STATUS_SUCCESS)
- {
- return(Status);
- }
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
PiTerminateProcessThreads(Process, ExitStatus);
- KeRaiseIrql(DISPATCH_LEVEL, &oldlvl);
- Process->Pcb.ProcessState = PROCESS_STATE_TERMINATED;
- Process->Pcb.DispatcherHeader.SignalState = TRUE;
- KeDispatcherObjectWake(&Process->Pcb.DispatcherHeader);
if (PsGetCurrentThread()->ThreadsProcess == Process)
- {
- KeLowerIrql(oldlvl);
- ObDereferenceObject(Process);
- PsTerminateCurrentThread(ExitStatus);
- }
- KeLowerIrql(oldlvl);
+ {
+ ObDereferenceObject(Process);
+ PsTerminateCurrentThread(ExitStatus);
+ }
ObDereferenceObject(Process);
return(STATUS_SUCCESS);
}
-NTSTATUS STDCALL NtTerminateThread(IN HANDLE ThreadHandle,
- IN NTSTATUS ExitStatus)
+NTSTATUS STDCALL
+NtTerminateThread(IN HANDLE ThreadHandle,
+ IN NTSTATUS ExitStatus)
{
PETHREAD Thread;
NTSTATUS Status;
{
return(Status);
}
-
+
+ ObDereferenceObject(Thread);
+
if (Thread == PsGetCurrentThread())
{
PsTerminateCurrentThread(ExitStatus);
}
-NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus)
+NTSTATUS STDCALL
+PsTerminateSystemThread(NTSTATUS ExitStatus)
/*
* FUNCTION: Terminates the current thread
* ARGUMENTS:
return(STATUS_SUCCESS);
}
+NTSTATUS STDCALL
+NtCallTerminatePorts(PETHREAD Thread)
+{
+ KIRQL oldIrql;
+ PLIST_ENTRY current_entry;
+ PEPORT_TERMINATION_REQUEST current;
+
+ KeAcquireSpinLock(&Thread->ActiveTimerListLock, &oldIrql);
+ while ((current_entry = RemoveHeadList(&Thread->TerminationPortList)) !=
+ &Thread->TerminationPortList);
+ {
+ current = CONTAINING_RECORD(current_entry,
+ EPORT_TERMINATION_REQUEST,
+ ThreadListEntry);
+ KeReleaseSpinLock(&Thread->ActiveTimerListLock, oldIrql);
+ LpcSendTerminationPort(current->Port,
+ Thread->CreateTime);
+ KeAcquireSpinLock(&Thread->ActiveTimerListLock, &oldIrql);
+ }
+ KeReleaseSpinLock(&Thread->ActiveTimerListLock, oldIrql);
+ return(STATUS_SUCCESS);
+}
-NTSTATUS STDCALL NtRegisterThreadTerminatePort(HANDLE TerminationPort)
+NTSTATUS STDCALL
+NtRegisterThreadTerminatePort(HANDLE TerminationPortHandle)
{
- UNIMPLEMENTED;
+ NTSTATUS Status;
+ PEPORT_TERMINATION_REQUEST Request;
+ PEPORT TerminationPort;
+ KIRQL oldIrql;
+ PETHREAD Thread;
+
+ Status = ObReferenceObjectByHandle(TerminationPortHandle,
+ PORT_ALL_ACCESS,
+ ExPortType,
+ UserMode,
+ (PVOID*)&TerminationPort,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+ Request = ExAllocatePool(NonPagedPool, sizeof(Request));
+ Request->Port = TerminationPort;
+ Thread = PsGetCurrentThread();
+ KeAcquireSpinLock(&Thread->ActiveTimerListLock, &oldIrql);
+ InsertTailList(&Thread->TerminationPortList, &Request->ThreadListEntry);
+ KeReleaseSpinLock(&Thread->ActiveTimerListLock, oldIrql);
+
+ return(STATUS_SUCCESS);
}