mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
348 lines
8.9 KiB
348 lines
8.9 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
consignl.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the handler for signals received from OS2SES.
|
|
|
|
Author:
|
|
|
|
Avi Nathan (avin) 17-Jul-1991
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#define INCL_OS2V20_TASKING
|
|
#define INCL_OS2V20_ERRORS
|
|
#define INCL_OS2V20_EXCEPTIONS
|
|
#include "os2srv.h"
|
|
#include "os2win.h"
|
|
|
|
#define NTOS2_ONLY
|
|
|
|
#define XCPT_REPLACE_CMD 12
|
|
|
|
#include "sesport.h"
|
|
|
|
VOID
|
|
Os2PrepareCmdSignals(POS2_PROCESS Process)
|
|
{
|
|
|
|
/*++
|
|
|
|
This routine installs a dummy signal handler, to mimique the signal
|
|
behavior of OS/2 CMD.EXE, in cases where we shortcut cmd /c for performance
|
|
|
|
--*/
|
|
|
|
POS2_SESSION Session;
|
|
POS2_REGISTER_HANDLER_REC pRec;
|
|
POS2_REGISTER_HANDLER_REC pPRec;
|
|
|
|
Session = Process->Session;
|
|
|
|
pPRec = (POS2_REGISTER_HANDLER_REC)
|
|
RtlAllocateHeap(Os2Heap, 0,
|
|
sizeof(OS2_REGISTER_HANDLER_REC));
|
|
if ((PVOID)pPRec == NULL) {
|
|
#if DBG
|
|
DbgPrint("Os2PrepareCmdSingals, no memory for heap, return with no action\n");
|
|
#endif
|
|
return;
|
|
}
|
|
pPRec->Signal = XCPT_REPLACE_CMD;
|
|
pPRec->fAction = XCPT_REPLACE_CMD;
|
|
pPRec->Process = Process;
|
|
|
|
|
|
if (Session->RegisterCtrlHandler == NULL) {
|
|
Session->RegisterCtrlHandler = pPRec;
|
|
pPRec->Link = NULL;
|
|
}
|
|
else {
|
|
pRec = Session->RegisterCtrlHandler;
|
|
Session->RegisterCtrlHandler = pPRec;
|
|
pPRec->Link = pRec;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
Os2SigKillProcess(
|
|
POS2_PROCESS Process)
|
|
{
|
|
POS2_THREAD Thread = NULL;
|
|
PLIST_ENTRY ListHead, ListNext;
|
|
OS2_API_MSG m;
|
|
POS2_TERMINATEPROCESS_MSG a = &m.u.TerminateProcess;
|
|
|
|
PORT_MSG_DATA_LENGTH(m) = sizeof(m) - sizeof(PORT_MESSAGE);
|
|
PORT_MSG_TOTAL_LENGTH(m) = sizeof(m);
|
|
PORT_MSG_ZERO_INIT(m) = 0L;
|
|
|
|
//
|
|
// Kill the process by issuing an Os2DosExit on it's behalf, then
|
|
// resume it to terminate gracefully
|
|
//
|
|
#if DBG
|
|
IF_OS2_DEBUG(SIG) {
|
|
DbgPrint("Os2SigKillProcess, Process %x\n", Process);
|
|
}
|
|
#endif
|
|
ListHead = &Process->ThreadList;
|
|
ListNext = ListHead->Flink;
|
|
Thread = NULL;
|
|
while (ListNext != ListHead) {
|
|
Thread = CONTAINING_RECORD(ListNext, OS2_THREAD, Link);
|
|
if (Thread->Flags & OS2_THREAD_THREAD1) {
|
|
break;
|
|
}
|
|
else {
|
|
ListNext = ListNext->Flink;
|
|
}
|
|
}
|
|
|
|
if (Thread != NULL) {
|
|
a->ExitReason = TC_EXIT;
|
|
a->ExitResult = ERROR_INTERRUPT;
|
|
((POS2_DOSEXIT_MSG)a)->ExitAction = EXIT_PROCESS;
|
|
|
|
if (Process->CtrlHandlerFlag) {
|
|
|
|
if (Process->ResultCodes.ExitReason != TC_TRAP) {
|
|
ULONG killed = TRUE;
|
|
NTSTATUS Status;
|
|
Status = NtWriteVirtualMemory( Process->ProcessHandle,
|
|
&Process->ClientPib->Killed,
|
|
&killed,
|
|
sizeof( Process->ClientPib->Killed ),
|
|
NULL
|
|
);
|
|
#if DBG
|
|
if (!(NT_SUCCESS(Status))) {
|
|
KdPrint(( "Os2SigKillProcess, failed to write to client, Status %lx\n", Status));
|
|
}
|
|
#endif // DBG
|
|
}
|
|
|
|
//
|
|
// set flag to create a separate thread for Os2DosExit
|
|
//
|
|
m.ApiNumber = Os2MaxApiNumber;
|
|
Os2DosExit (Thread, &m);
|
|
#if DBG
|
|
IF_OS2_DEBUG(SIG) {
|
|
DbgPrint("now resuming thread1\n");
|
|
}
|
|
#endif
|
|
// NtResumeThread(Thread->ThreadHandle, NULL);
|
|
|
|
// There is no need to alert thread here. It will be executed later
|
|
// by Os2TerminationThread.
|
|
//
|
|
//#if DBG
|
|
// DbgPrint("[%d,%d]: Os2SigKillProcess NtAlertThread(%x)\n",
|
|
// Thread->Process->ProcessId,
|
|
// Thread->ThreadId,
|
|
// Thread->ThreadHandle);
|
|
//#endif
|
|
// NtAlertThread(Thread->ThreadHandle);
|
|
}
|
|
else {
|
|
#if DBG
|
|
IF_OS2_DEBUG(SIG) {
|
|
DbgPrint("OS2SRV: Handling a signal before loading completed\n");
|
|
}
|
|
#endif
|
|
Process->ExitStatus |= OS2_EXIT_IN_PROGRESS;
|
|
Os2InternalTerminateProcess(Thread, &m);
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
Os2SigKillProcessTree(
|
|
IN POS2_PROCESS RootProcess,
|
|
IN BOOLEAN IncludeRoot
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine recursively kills each subtree inside it
|
|
|
|
Arguments:
|
|
|
|
RootProcess - root process of tree to issue Signal to
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
PLIST_ENTRY ListHead, ListNext;
|
|
|
|
if (IncludeRoot){
|
|
#if DBG
|
|
IF_OS2_DEBUG(SIG) {
|
|
DbgPrint("SigKillProcessTree, killing parent\n");
|
|
}
|
|
#endif
|
|
Os2SigKillProcess(RootProcess);
|
|
}
|
|
|
|
ListHead = &RootProcess->ChildrenList;
|
|
ListNext = ListHead->Flink;
|
|
while (ListNext != ListHead) {
|
|
#if DBG
|
|
IF_OS2_DEBUG(SIG) {
|
|
DbgPrint("SigKillProcessTree, getting into recursion\n");
|
|
}
|
|
#endif
|
|
Os2SigKillProcessTree( CONTAINING_RECORD( ListNext,OS2_PROCESS,SiblingLink),
|
|
TRUE
|
|
);
|
|
ListNext = ListNext->Flink;
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
Os2CtrlSignalHandler(
|
|
IN OUT PVOID RequestMsg,
|
|
IN POS2_PROCESS RecievingProcess
|
|
)
|
|
{
|
|
POS2_PROCESS Process, Parent = NULL;
|
|
POS2_THREAD Thread = NULL;
|
|
PLIST_ENTRY ListHead, ListNext;
|
|
int Signal = ((POS2SESREQUESTMSG)RequestMsg)->d.Signal.Type;
|
|
POS2_SESSION Session = (POS2_SESSION)(((POS2SESREQUESTMSG)RequestMsg)->Session);
|
|
POS2_REGISTER_HANDLER_REC pRec;
|
|
|
|
|
|
#if DBG
|
|
IF_OS2_DEBUG(SIG) {
|
|
DbgPrint("Os2CtrlSignalHandler: Signal %x for Session %p\n", Signal, Session);
|
|
}
|
|
#endif
|
|
|
|
if (Session == NULL) {
|
|
#if DBG
|
|
DbgPrint("Os2CtrlSignalHandler: NULL Session Passed\n");
|
|
#endif
|
|
return STATUS_INVALID_HANDLE;
|
|
}
|
|
|
|
if ((Signal != XCPT_SIGNAL_INTR ) &&
|
|
(Signal != XCPT_SIGNAL_KILLPROC ) &&
|
|
(Signal != XCPT_SIGNAL_BREAK )){
|
|
#if DBG
|
|
DbgPrint("Os2CtrlSignalHandler: Unknown Signal %x\n", Signal);
|
|
#endif
|
|
return (0L);
|
|
}
|
|
|
|
if (Session->InTermination)
|
|
{
|
|
#if DBG
|
|
IF_OS2_DEBUG(SIG) {
|
|
DbgPrint("Os2CtrlSignalHandler: session in termination already\n");
|
|
}
|
|
#endif
|
|
return (0L);
|
|
}
|
|
|
|
//
|
|
// If a process in this session has registered a handler for Ctrl-c,
|
|
// Kill process or Ctrl-break dispatch only to this one otherwise
|
|
// send a signal to each process
|
|
//
|
|
if ((pRec = Session->RegisterCtrlHandler) != NULL) {
|
|
while (pRec != NULL) {
|
|
if (pRec->Signal == (ULONG) Signal) {
|
|
//
|
|
// Since we receive a debug message for each process
|
|
// in the session, no need to forward except for
|
|
// the process who actually handles the Signal
|
|
//
|
|
if ((pRec->Process == RecievingProcess) || (RecievingProcess == NULL)) {
|
|
if (pRec->fAction != SIGA_IGNORE){
|
|
Os2IssueSignal(pRec->Process, Signal);
|
|
}
|
|
}
|
|
return(0L);
|
|
}
|
|
else if (pRec->Signal == XCPT_REPLACE_CMD) {
|
|
//
|
|
// We replaced (performance) exec of cmd /c with direct
|
|
// exec of it's children, and none of them registered
|
|
// A handler for this signal - kill the subtree
|
|
//
|
|
Os2SigKillProcessTree(pRec->Process, TRUE);
|
|
return(0L);
|
|
}
|
|
pRec = pRec->Link;
|
|
}
|
|
}
|
|
|
|
//
|
|
// We need to send a signal to each process in this session. First
|
|
// suspend each process in this session.
|
|
//
|
|
|
|
for (
|
|
ListHead = &Os2RootProcess->ListLink,
|
|
ListNext = ListHead->Flink;
|
|
ListNext != ListHead ;
|
|
ListNext = ListNext->Flink
|
|
) {
|
|
Process = CONTAINING_RECORD( ListNext, OS2_PROCESS, ListLink );
|
|
if ( Process->Session == Session ) {
|
|
Os2SuspendProcess(Process);
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// After each process has been suspended kill each one
|
|
//
|
|
ListHead = &Os2RootProcess->ListLink;
|
|
ListNext = ListHead->Flink;
|
|
while (ListNext != ListHead) {
|
|
|
|
Process = CONTAINING_RECORD(ListNext, OS2_PROCESS, ListLink);
|
|
ListNext = ListNext->Flink;
|
|
|
|
if ( Process->Session == Session ) {
|
|
Os2SigKillProcess(Process);
|
|
}
|
|
}
|
|
|
|
//
|
|
// This Session should not respond to any more signals until it terminates
|
|
//
|
|
try {
|
|
Session->InTermination = TRUE;
|
|
if (Session->ReferenceCount != -1L)
|
|
{
|
|
((POS2_SES_GROUP_PARMS)Session->SesGrpAddress)->InTermination |= 1;
|
|
}
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
#if DBG
|
|
IF_OS2_DEBUG(SIG) {
|
|
DbgPrint("OS2SRV: Os2CtrlSignalHandler Got an Exception, recovery ok\n");
|
|
}
|
|
#endif
|
|
;
|
|
}
|
|
return(0L);
|
|
}
|
|
|