summaryrefslogtreecommitdiffstats
path: root/private/os2/server/consignl.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/os2/server/consignl.c')
-rw-r--r--private/os2/server/consignl.c348
1 files changed, 348 insertions, 0 deletions
diff --git a/private/os2/server/consignl.c b/private/os2/server/consignl.c
new file mode 100644
index 000000000..cb76e4f35
--- /dev/null
+++ b/private/os2/server/consignl.c
@@ -0,0 +1,348 @@
+/*++
+
+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);
+}
+