News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Console App and CTRL-C

Started by cobold, May 16, 2009, 01:59:40 PM

Previous topic - Next topic

cobold

Hello,
one can interrupt a running console-app by pressing CTRL-C or CTRL-BREAK.

Question 1:
   Does CTRL-C close or handles, files, etc. automatically? (I think so, but am not sure)
Question 2:
   Is it possible that a program detects if CTRL-C was pressed, so that it can perform some closing-tasks, i.e. save temporary results and then give back program-flow to CTRL-C-handler?

Thanks in advance for help!

cobold

Neil

My understanding is that CTRL-C does some housekeeping before calling  CTRL-BREAK.
CTRL-BREAK terminates the program Immediately.
If you are talking about 16 bit programming then you can re-program the interrupt, I don't know of any API that can do this for 32 bit although others might.

MichaelW

The default handler calls ExitProcess, closing handles, terminating threads, etc, but you can install your own handler to do whatever. See SetConsoleCtrlHandler.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

HandlerRoutine proc dwCtrlType:DWORD

    SWITCH dwCtrlType

      CASE CTRL_C_EVENT

        print "CTRL_C_EVENT"
        invoke Sleep, 2000

      CASE CTRL_CLOSE_EVENT

        print "CTRL_CLOSE_EVENT"
        invoke Sleep, 2000

      CASE CTRL_BREAK_EVENT

        print "CTRL_BREAK_EVENT"
        invoke Sleep, 2000

      CASE CTRL_LOGOFF_EVENT

        print "CTRL_LOGOFF_EVENT"
        invoke Sleep, 2000

      CASE CTRL_SHUTDOWN_EVENT

        print "CTRL_SHUTDOWN_EVENT"
        invoke Sleep, 2000

    ENDSW

    ;---------------------------------------------------------------
    ; Return FALSE so the control signal will be passed to the next
    ; handler in the list (the default handler, in this case).
    ;---------------------------------------------------------------

    return FALSE

HandlerRoutine endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    invoke SetConsoleCtrlHandler, HandlerRoutine, TRUE

    ;-----------------------------------------------------
    ; Wait for the default handler to terminate the app.
    ; The Sleep(10) avoids hogging the CPU while waiting.
    ;-----------------------------------------------------

    .WHILE 1
      invoke Sleep, 10
    .ENDW

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start

eschew obfuscation

cobold

Michael,

thanks a lot for your helpful reply. It gave me exactly the information I needed. Have you memorized the win-api?   :U
Your example is well commented, still there's something I don't understand:
What exactly is the while loop doing (.while 1) Does it refer to the return value of SetConsoleCtrlHandler?
    invoke SetConsoleCtrlHandler, HandlerRoutine, TRUE
    ;-----------------------------------------------------
    ; Wait for the default handler to terminate the app.
    ; The Sleep(10) avoids hogging the CPU while waiting.
    ;-----------------------------------------------------

    .WHILE 1 ; should be .if (eax !=0) [if return value is nonzero --> success???]
      invoke Sleep, 10
    .ENDW


BlackVortex

".while 1" just means that the condition will always be true ... forever.

MichaelW

The .WHILE 1 is just one of many ways to create an endless loop. It could just as well (and probably should) have been:
@@:
  invoke Sleep,10
  jmp @B
eschew obfuscation

CObject

What about child cmd.exe process created by call :


CreateProcessA(NULL, "cmd.exe", NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &info);


and communications between parent and child processes are done only by pipes ?

How to send Ctrl-C signal from parent to child (cmd.exe) process in this situation ?

For example when sending 'ping -t masm32.com' command through pipe to cmd.exe, child process blocks, but continue to send data back to parent process.
Do I have to restart my command-sending thread and child process itself ?

Currently I look for a 'ping' process using its PID and terminate it.

BlackVortex

Complicated stuff. By reading around I found some useful info :

http://msdn.microsoft.com/en-us/library/ms683155%28VS.85%29.aspx
QuoteGenerateConsoleCtrlEvent Function

Sends a specified signal to a console process group that shares the console associated with the calling process.

http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx
Quote
When a process is created with CREATE_NEW_PROCESS_GROUP specified, an implicit call to SetConsoleCtrlHandler(NULL,TRUE) is made on behalf of the new process; this means that the new process has CTRL+C disabled. This lets shells handle CTRL+C themselves, and selectively pass that signal on to sub-processes. CTRL+BREAK is not disabled, and may be used to interrupt the process/process group.

http://msdn.microsoft.com/en-us/library/ms686016%28VS.85%29.aspx
QuoteSetConsoleCtrlHandler Function

Adds or removes an application-defined HandlerRoutine function from the list of handler functions for the calling process.

If no handler function is specified, the function sets an inheritable attribute that determines whether the calling process ignores CTRL+C signals.

So, I guess you can use GenerateConsoleCtrlEvent with the CTRL_BREAK_EVENT parameter  :toothy

CObject

GenerateConsoleCtrlEvent Function doesn't work in my situation. It's strange but I look around in the www and found that many people claim the same.
More, CTRL+BREAK doesn't terminate command 'ping -t masm32.com'. Start command prompt and try it.

I think I have 2 other workaround solutions:

1. To create console app which I can use as child process. And inside this console app to make ctrl_c not to be interpreted as a signal, then I must be able to write 0x03 ASCII code to pipe from parent process.
It is possible also to create 3rd (named) pipe especially for terminate events.

2. To inject a DLL into child process.