Fixed synchronisation for ctrl event generation.

This commit is contained in:
Eric Pouech 2002-07-10 20:31:46 +00:00 committed by Alexandre Julliard
parent d386fa75bc
commit b810b53b0a
1 changed files with 95 additions and 67 deletions

View File

@ -474,51 +474,72 @@ static BOOL WINAPI CONSOLE_DefaultHandler(DWORD dwCtrlType)
* This doesn't yet matter, since these handlers are not yet called...! * This doesn't yet matter, since these handlers are not yet called...!
*/ */
static unsigned int console_ignore_ctrl_c = 0; /* FIXME: this should be inherited somehow */ struct ConsoleHandler {
static PHANDLER_ROUTINE handlers[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,CONSOLE_DefaultHandler}; PHANDLER_ROUTINE handler;
struct ConsoleHandler* next;
};
static unsigned int CONSOLE_IgnoreCtrlC = 0; /* FIXME: this should be inherited somehow */
static struct ConsoleHandler CONSOLE_DefaultConsoleHandler = {CONSOLE_DefaultHandler, NULL};
static struct ConsoleHandler* CONSOLE_Handlers = &CONSOLE_DefaultConsoleHandler;
static CRITICAL_SECTION CONSOLE_CritSect = CRITICAL_SECTION_INIT("console_ctrl_section");
/*****************************************************************************/ /*****************************************************************************/
BOOL WINAPI SetConsoleCtrlHandler(PHANDLER_ROUTINE func, BOOL add) BOOL WINAPI SetConsoleCtrlHandler(PHANDLER_ROUTINE func, BOOL add)
{ {
int alloc_loop = sizeof(handlers)/sizeof(handlers[0]) - 1; BOOL ret = TRUE;
FIXME("(%p,%i) - no error checking or testing yet\n", func, add); FIXME("(%p,%i) - no error checking or testing yet\n", func, add);
if (!func) if (!func)
{ {
console_ignore_ctrl_c = add; CONSOLE_IgnoreCtrlC = add;
return TRUE;
} }
if (add) else if (add)
{ {
for (; alloc_loop >= 0 && handlers[alloc_loop]; alloc_loop--); struct ConsoleHandler* ch = HeapAlloc(GetProcessHeap(), 0, sizeof(struct ConsoleHandler));
if (alloc_loop <= 0)
{ if (!ch) return FALSE;
FIXME("Out of space on CtrlHandler table\n"); ch->handler = func;
return FALSE; EnterCriticalSection(&CONSOLE_CritSect);
} ch->next = CONSOLE_Handlers;
handlers[alloc_loop] = func; CONSOLE_Handlers = ch;
LeaveCriticalSection(&CONSOLE_CritSect);
} }
else else
{ {
for (; alloc_loop >= 0 && handlers[alloc_loop] != func; alloc_loop--); struct ConsoleHandler** ch;
if (alloc_loop <= 0) EnterCriticalSection(&CONSOLE_CritSect);
for (ch = &CONSOLE_Handlers; *ch; *ch = (*ch)->next)
{ {
WARN("Attempt to remove non-installed CtrlHandler %p\n", func); if ((*ch)->handler == func) break;
return FALSE;
} }
if (*ch)
{
struct ConsoleHandler* rch = *ch;
/* sanity check */ /* sanity check */
if (alloc_loop == sizeof(handlers)/sizeof(handlers[0]) - 1) if (rch == &CONSOLE_DefaultConsoleHandler)
{ {
ERR("Who's trying to remove default handler???\n"); ERR("Who's trying to remove default handler???\n");
return FALSE; ret = FALSE;
} }
if (alloc_loop) else
memmove(&handlers[1], &handlers[0], alloc_loop * sizeof(handlers[0])); {
handlers[0] = 0; rch = *ch;
*ch = (*ch)->next;
HeapFree(GetProcessHeap(), 0, rch);
} }
return TRUE; }
else
{
WARN("Attempt to remove non-installed CtrlHandler %p\n", func);
ret = FALSE;
}
LeaveCriticalSection(&CONSOLE_CritSect);
}
return ret;
} }
static WINE_EXCEPTION_FILTER(CONSOLE_CtrlEventHandler) static WINE_EXCEPTION_FILTER(CONSOLE_CtrlEventHandler)
@ -527,6 +548,51 @@ static WINE_EXCEPTION_FILTER(CONSOLE_CtrlEventHandler)
return EXCEPTION_EXECUTE_HANDLER; return EXCEPTION_EXECUTE_HANDLER;
} }
static DWORD WINAPI CONSOLE_HandleCtrlCEntry(void* pmt)
{
struct ConsoleHandler* ch;
EnterCriticalSection(&CONSOLE_CritSect);
/* the debugger didn't continue... so, pass to ctrl handlers */
for (ch = CONSOLE_Handlers; ch; ch = ch->next)
{
if (ch->handler((DWORD)pmt)) break;
}
LeaveCriticalSection(&CONSOLE_CritSect);
return 0;
}
/******************************************************************
* CONSOLE_HandleCtrlC
*
* Check whether the shall manipulate CtrlC events
*/
int CONSOLE_HandleCtrlC(void)
{
/* FIXME: better test whether a console is attached to this process ??? */
extern unsigned CONSOLE_GetNumHistoryEntries(void);
if (CONSOLE_GetNumHistoryEntries() == (unsigned)-1) return 0;
if (CONSOLE_IgnoreCtrlC) return 1;
/* try to pass the exception to the debugger
* if it continues, there's nothing more to do
* otherwise, we need to send the ctrl-event to the handlers
*/
__TRY
{
RaiseException( DBG_CONTROL_C, 0, 0, NULL );
}
__EXCEPT(CONSOLE_CtrlEventHandler)
{
/* Create a separate thread to signal all the events. This would allow to
* synchronize between setting the handlers and actually calling them
*/
CreateThread(NULL, 0, CONSOLE_HandleCtrlCEntry, (void*)CTRL_C_EVENT, 0, NULL);
}
__ENDTRY;
return 1;
}
/****************************************************************************** /******************************************************************************
* GenerateConsoleCtrlEvent [KERNEL32.@] Simulate a CTRL-C or CTRL-BREAK * GenerateConsoleCtrlEvent [KERNEL32.@] Simulate a CTRL-C or CTRL-BREAK
* *
@ -1379,41 +1445,3 @@ unsigned CONSOLE_GetNumHistoryEntries(void)
SERVER_END_REQ; SERVER_END_REQ;
return ret; return ret;
} }
/******************************************************************
* CONSOLE_HandleCtrlC
*
* Check whether the shall manipulate CtrlC events
*/
int CONSOLE_HandleCtrlC(void)
{
int i;
/* FIXME: better test whether a console is attached to this process ??? */
extern unsigned CONSOLE_GetNumHistoryEntries(void);
if (CONSOLE_GetNumHistoryEntries() == (unsigned)-1) return 0;
/* try to pass the exception to the debugger
* if it continues, there's nothing more to do
* otherwise, we need to send the ctrl-event to the handlers
*/
__TRY
{
RaiseException( DBG_CONTROL_C, 0, 0, NULL );
}
__EXCEPT(CONSOLE_CtrlEventHandler)
{
/* the debugger didn't continue... so, pass to ctrl handlers */
/* FIXME: since this routine is called while in a signal handler,
* there are some serious synchronisation issues with
* SetConsoleCtrlHandler (trouble ahead)
*/
for (i = 0; i < sizeof(handlers)/sizeof(handlers[0]); i++)
{
if (handlers[i] && (handlers[i])(CTRL_C_EVENT)) break;
}
}
__ENDTRY;
return 1;
}