From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29126 invoked by alias); 17 Apr 2008 11:59:48 -0000 Received: (qmail 29114 invoked by uid 22791); 17 Apr 2008 11:59:47 -0000 X-Spam-Check-By: sourceware.org Received: from mail2.br-automation.com (HELO mail2.br-automation.com) (213.33.116.61) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 17 Apr 2008 11:59:15 +0000 X-AuditID: c0a80110-ab95dbb000001b77-24-48073b8f9334 Received: from brsmtp01.br-automation.com (unknown [192.168.1.60]) by mail2.br-automation.com (Symantec Mail Security) with ESMTP id 84E414DC003; Thu, 17 Apr 2008 13:59:11 +0200 (CEST) In-Reply-To: <53d46f3a0804170310p40a048dfo49302e8b720ba7cb@mail.gmail.com> MIME-Version: 1.0 To: "Roberto Saltini" Cc: gdb@sourceware.org Subject: Re: Interrupting a running program X-Mailer: Lotus Notes Release 7.0.2 September 26, 2006 Message-ID: From: Roland Puntaier Date: Fri, 18 Apr 2008 11:10:00 -0000 Content-Type: text/plain; charset="US-ASCII" X-IsSubscribed: yes Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2008-04/txt/msg00170.txt.bz2 Hi, gdb-owner@sourceware.org wrote on 2008/04/17 12:10:23: > Hello, > I am emulating a program written for an embedded system. This means I > have a main which loop continuosly. > Problem with gdb is that if I run the program I lose gdb input console > and threfor I am not able to interrupt the program execution or insert > a break point. > How could I solve my problem? > Thank you. > > -- > Saltini Roberto I had the same problem. I suppose you use Windows with MinGW. If Yes, then the following might help you. I interpret the CLI, because there is also a console interface and the user should get from GDB what he is used, i.e. the CLI output. (I must say that I did not go into depth to find out how this is possible with MI and also I don't know whether MI provides a solution to the problem, that gdb is not responsive while the inferior is running. Maybe someone else can tell you that. I did also not test the possibilities of libmigdb about which was posted here recently.) One can send GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); to GDB, but this works only from a console application. For this reason I made a Console Wrapper that calls the function as a response to a windows event. Futher down are the sources. They are based on sources I found in the internet. I use GDB 6.6 and still had a problem that GDB hanged after Ctrl-C. The solution can be found in http://www.cygwin.com/ml/gdb/2007-08/msg00181.html. When GDB is interrupted the gdbserver is abandoned and it must start listening again maintaining its internal state and queuing breakpoints that might come in the meantime. When GDB reconnects its remote commands like setting new BPs must be executed, but resume on the inferior can only be made if no BPs are queued. Instead queued BPs must be return to GDB. Hope this helps. Cheers. Console Wrapper Sources: #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include #include #include #include //this is an adaptation of http://www.codeproject.com/threads/RTconsole.asp. #define SLEEP_TIME 50 // reactivity: sleep time to wait for subprocess to output some more data CONST COORD origin = { 0, 0 }; // we should have been spawned using SW_HIDE, so our console window is not visible int main(int argc, char* argv[]) { // get pipe/console to output to HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); DWORD dwDummy; if (argc < 4) { _tprintf(__TEXT("Usage: %s (InheritableEventHandle for CtrlC|0) (InheritableEventHandle for Terminate|0) (CommandLineToSpawn)\n" ), argv[0]); return(0); } TCHAR commandLine[1024] = { 0 }; for (int x = 3; x < argc; x++) { strcat_s(commandLine, argv[x]); strcat_s(commandLine, __TEXT(" ")); } HANDLE evtCtrlC = (HANDLE)atol(argv[1]); HANDLE evtTerminate = (HANDLE)atol(argv[2]); if (evtCtrlC!=0) ResetEvent(evtCtrlC); if (evtTerminate!=0) ResetEvent(evtTerminate); // prepare the console window & inherited screen buffer SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; HANDLE hConsole = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,&sa,CONSOLE_TEXTMODE_BUFFER,NULL); FillConsoleOutputCharacter(hConsole, '\0', MAXLONG, origin, &dwDummy); // fill screen buffer with zeroes SetConsoleActiveScreenBuffer(hConsole); // start the subprocess PROCESS_INFORMATION pi; STARTUPINFO si; ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_FORCEOFFFEEDBACK; // we don't want the "app starting" cursor // all other default options are already good : we want subprocess to share the same console and to inherit our STD handles if (!CreateProcess(NULL, commandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { CloseHandle(hConsole); return -2; } CloseHandle(pi.hThread); // always close the hThread after a CreateProcess SetConsoleCtrlHandler(NULL, TRUE);//only let gdb handle CTRL-C COORD lastpos = { 0, 0 }; CONSOLE_SCREEN_BUFFER_INFO csbi; bool exitNow = false; do { if (WaitForSingleObject(pi.hProcess, 0) != WAIT_TIMEOUT) exitNow = true; // exit after this last iteration // get screen buffer state GetConsoleScreenBufferInfo(hConsole, &csbi); int lineWidth = csbi.dwSize.X; if ((csbi.dwCursorPosition.X == lastpos.X) && (csbi.dwCursorPosition.Y == lastpos.Y)) { HANDLE handles[2]; handles[0] = evtCtrlC; handles[1] = evtTerminate; DWORD wait_res = WaitForMultipleObjects(2,handles,FALSE,SLEEP_TIME); if (wait_res==WAIT_OBJECT_0) { GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); } else if (wait_res==WAIT_OBJECT_0+1) { TerminateProcess(pi.hProcess,0); } else if (wait_res != WAIT_TIMEOUT) Sleep(SLEEP_TIME); } else { DWORD count = (csbi.dwCursorPosition.Y-lastpos.Y)*lineWidth+csbi.dwCursorPosition.X-lastpos.X; // read newly output characters starting from last cursor position LPTSTR buffer = (LPTSTR) LocalAlloc(0, count* sizeof(TCHAR)); ReadConsoleOutputCharacter(hConsole, buffer, count, lastpos, &count); // fill screen buffer with zeroes FillConsoleOutputCharacter(hConsole, '\0', count, lastpos, &dwDummy); SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); lastpos = csbi.dwCursorPosition; GetConsoleScreenBufferInfo(hConsole, &csbi); if ((csbi.dwCursorPosition.X == lastpos.X) && (csbi.dwCursorPosition.Y == lastpos.Y)) { // text cursor did not move since this treatment, hurry to reset it to home SetConsoleCursorPosition(hConsole, origin); lastpos = origin; } SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); // scan screen buffer and transmit character to real output handle LPTSTR scan = buffer; do { if (*scan) { DWORD len = 1; while (scan[len] && (len < count)) len++; WriteFile(hOutput, scan, len, &dwDummy, NULL); scan += len; count -= len; } else { DWORD len = 1; while (!scan[len] && (len < count)) len++; scan += len; count -= len; len = (len+lineWidth-1)/lineWidth; for (;len;len--) WriteFile(hOutput, "\r\n", 2, &dwDummy, NULL); } } while (count); //FlushFileBuffers(hOutput); // seems unnecessary LocalFree(buffer); } // loop until end of subprocess } while (!exitNow); SetConsoleCtrlHandler(NULL, FALSE); CloseHandle(hConsole); // release subprocess handle DWORD exitCode; if (!GetExitCodeProcess(pi.hProcess, &exitCode)) exitCode = -3; CloseHandle(pi.hProcess); return exitCode; }