This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: GDB Ctrl-C Interrupt Fails WORKAROUND


On 15 Jun 2006 11:04:56 -0400, Christopher Faylor wrote:
>Lacking the ability to interrupt a running program severely limits
>gdb's usefulness.  Fortunately there's a workaround available.

Yep. Use a console window.

Maybe I haven't been clear. THIS DOES NOT WORK.


Compile the below hellowin.c program with the m$ visual C compiler. Start it up using gdb. Run it, press CTRL-C, NOTHING HAPPENS.

/* BEGIN hellowin.c */

/* compile with "cl -o hellowin.exe hellowin.c user32.lib" */

#include <windows.h>
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow)
{
MessageBox(NULL, "Hello, world!", "", MB_OK);
return 0;
}


/* END hellowin.c */

Now if you have such a program compiled with the m$ compiler for which you do not have the source and such a program is loading a DLL plugin built with cygwin that you're trying to debug then CTRL-C WILL NEVER WORK no matter how many console windows you get out.

A console window is also not an option when debugging via a remote X session or ssh.

On 15 Jun 2006 10:43:23 -0400 , Igor Peshansky wrote:
Does "kill -INT <cygwin_pid>" work?

No.


The workaround would be even better if you didn't need a separate program.
How about submitting a patch for Cygwin's "kill" (with a new signal,
SIGDBG or SIGDEBUG)? CGF, would you consider such a patch?

That would be nice, for both kill and killall. I provided the very simple source code in my original message (and included again in this one for your convenience) so anyone could use it right away or make a patch if they like. The relevant code is:


HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD) winpid_proc_id);
if (proc != NULL) {DebugBreakProcess(proc); CloseHandle(proc);}


On 15 Jun 2006 01:28:59 -0700 , clayne at anodized dot wrote:
BTW Kyle, you can extend your program greatly by using process enumeration
coupled with strcmp on the image name to find the pid based on a string and
automatically signal it.

Yes, or you could just use the below two-line shell script:


#!/bin/sh
ps -W | grep "$1" | awk '{print $1}' | xargs -n 1 debugbreak

But honestly I don't think this program should be needed in the first place.

Neither do I. gdb was not usable for me previously. The console window option DOES NOT WORK when the program loading the cygwin-built DLL was compiled with m$ visual C. It is also a non-solution for ssh users and remote X users.


Here is the simple debugbreak.c source again.

Kyle

/* BEGIN debugbreak.c */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif

#if _WIN32_WINNT < 0x0501
#error Must target Windows NT 5.0.1 or later for DebugBreakProcess
#endif

#include <Windows.h>
#include <stddef.h>
#include <stdlib.h>

/* Compile with this line:

gcc -o debugbreak -mno-cygwin -mthreads debugbreak.c

*/

static char errbuffer[256];

static const char *geterrstr(DWORD errcode)
{
size_t skip = 0;
DWORD chars;
chars = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errcode, 0, errbuffer, sizeof(errbuffer)-1, 0);
errbuffer[sizeof(errbuffer)-1] = 0;
if (chars) {
while (errbuffer[chars-1] == '\r' || errbuffer[chars-1] == '\n') {
errbuffer[--chars] = 0;
}
}
if (chars && errbuffer[chars-1] == '.') errbuffer[--chars] = 0;
if (chars >= 2 && errbuffer[0] == '%' && errbuffer[1] >= '0'
&& errbuffer[1] <= '9')
{
skip = 2;
while (chars > skip && errbuffer[skip] == ' ') ++skip;
if (chars >= skip+2 && errbuffer[skip] == 'i'
&& errbuffer[skip+1] == 's')
{
skip += 2;
while (chars > skip && errbuffer[skip] == ' ') ++skip;
}
}
if (chars > skip && errbuffer[skip] >= 'A' && errbuffer[skip] <= 'Z') {
errbuffer[skip] += 'a' - 'A';
}
return errbuffer+skip;
}


int main(int argc, char *argv[])
{
    HANDLE proc;
    unsigned proc_id = 0;
    BOOL break_result;

    if (argc != 2) {
        printf("Usage: debugbreak process_id_number\n");
        return 1;
    }
    proc_id = (unsigned) strtol(argv[1], NULL, 0);
    if (proc_id == 0) {
        printf("Invalid process id %u\n", proc_id);
        return 1;
    }
    proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)proc_id);
    if (proc == NULL) {
        DWORD lastError = GetLastError();
        printf("Failed to open process %u\n", proc_id);
        printf("Error code is %lu (%s)\n", (unsigned long)lastError,
            geterrstr(lastError));
        return 1;
    }
    break_result = DebugBreakProcess(proc);
    if (!break_result) {
        DWORD lastError = GetLastError();
        printf("Failed to debug break process %u\n", proc_id);
        printf("Error code is %lu (%s)\n", (unsigned long)lastError,
            geterrstr(lastError));
        CloseHandle(proc);
        return 1;
    }
    printf("DebugBreak sent successfully to process id %u\n", proc_id);
    CloseHandle(proc);
    return 0;
}

/* END debugbreak.c */

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]