IBM1130: Cleanup GUI command interactions and shutdown activities
Cleaned up a couple of things here. Specifically: 1) scp_reading is only set when CmdThread is actually reading. 2) Avoid calling ResetEvent(hCmdReadEvent) since it has no effect. 3) Calling ReadFile directly rather than calling read_line which ultimately calls fgets(stdin) and that ultimately calls ReadFile. 4) Added a cleanup mechanism to shutdown the CmdThread and related open handles to Events and Thread when the program exits. Remaining potential problems: 1) A user might have type a partial command (scp_reading) but not completed it by hitting Enter, and then they perform some GUI interaction which does other things. Some strange output will be produced on top of the partially entered command line. 2) Whether or not a complete command has been entered, the original CmdThread will have a read posted on stdin throughout any activity initiated by GUI activities. It is not clear that the simulator’s console will coherently be able to change the console’s mode from the line oriented mode that SCP uses to the character oriented mode used while instructions are executing with read pending on the input side.
This commit is contained in:
parent
0c27d1f5a8
commit
b866f76af7
1 changed files with 42 additions and 15 deletions
|
@ -1523,21 +1523,54 @@ static HANDLE hCmdReadEvent = NULL;
|
||||||
static HANDLE hCmdReadyEvent = NULL;
|
static HANDLE hCmdReadyEvent = NULL;
|
||||||
static BOOL scp_stuffed = FALSE, scp_reading = FALSE;
|
static BOOL scp_stuffed = FALSE, scp_reading = FALSE;
|
||||||
static char cmdbuffer[256];
|
static char cmdbuffer[256];
|
||||||
|
static BOOL read_exiting = FALSE;
|
||||||
|
|
||||||
/* CmdThread - separate thread to read commands from stdin upon request */
|
/* CmdThread - separate thread to read commands from stdin upon request */
|
||||||
|
|
||||||
static DWORD WINAPI CmdThread (LPVOID arg)
|
static DWORD WINAPI CmdThread (LPVOID arg)
|
||||||
{
|
{
|
||||||
|
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
DWORD dwBytesRead;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
WaitForSingleObject(hCmdReadEvent, INFINITE); /* wait for request */
|
if (WAIT_TIMEOUT == WaitForSingleObject(hCmdReadEvent, 2000)) /* wait for request */
|
||||||
read_line(cmdbuffer, sizeof(cmdbuffer), stdin); /* read one line */
|
continue; /* put breakpoint here to debug */
|
||||||
|
if (read_exiting)
|
||||||
|
break;
|
||||||
|
scp_reading = TRUE;
|
||||||
|
if (ReadFile(hStdIn, cmdbuffer, sizeof(cmdbuffer)-1, &dwBytesRead, NULL)) {
|
||||||
|
cmdbuffer[dwBytesRead] = '\0';
|
||||||
scp_stuffed = FALSE; /* say how we got it */
|
scp_stuffed = FALSE; /* say how we got it */
|
||||||
scp_reading = FALSE;
|
scp_reading = FALSE;
|
||||||
SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */
|
SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */
|
||||||
|
} else {
|
||||||
|
DWORD dwError = GetLastError();
|
||||||
|
scp_reading = FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void read_atexit (void)
|
||||||
|
{
|
||||||
|
typedef BOOL (WINAPI *_func)(HANDLE, LPOVERLAPPED);
|
||||||
|
_func pCancelIoEx;
|
||||||
|
|
||||||
|
read_exiting = TRUE;
|
||||||
|
pCancelIoEx = (_func)GetProcAddress(GetModuleHandleA("kernel32.dll"), "CancelIoEx");
|
||||||
|
if (pCancelIoEx) {
|
||||||
|
pCancelIoEx(GetStdHandle(STD_INPUT_HANDLE), NULL);
|
||||||
|
SetEvent(hCmdReadEvent); /* wake read thread */
|
||||||
|
WaitForSingleObject(hCmdThread, INFINITE);
|
||||||
|
}
|
||||||
|
CloseHandle(hCmdReadyEvent);
|
||||||
|
hCmdReadyEvent = NULL;
|
||||||
|
CloseHandle(hCmdReadEvent);
|
||||||
|
hCmdReadEvent = NULL;
|
||||||
|
CloseHandle(hCmdThread);
|
||||||
|
hCmdThread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
char *read_cmdline (char *ptr, int size, FILE *stream)
|
char *read_cmdline (char *ptr, int size, FILE *stream)
|
||||||
{
|
{
|
||||||
char *cptr;
|
char *cptr;
|
||||||
|
@ -1551,10 +1584,9 @@ char *read_cmdline (char *ptr, int size, FILE *stream)
|
||||||
/* start up the command thread */
|
/* start up the command thread */
|
||||||
if ((hCmdThread = CreateThread(NULL, 0, CmdThread, NULL, 0, &iCmdThreadID)) == NULL)
|
if ((hCmdThread = CreateThread(NULL, 0, CmdThread, NULL, 0, &iCmdThreadID)) == NULL)
|
||||||
scp_panic("Unable to create command line reading thread");
|
scp_panic("Unable to create command line reading thread");
|
||||||
|
atexit(read_atexit);
|
||||||
}
|
}
|
||||||
|
|
||||||
scp_reading = TRUE;
|
|
||||||
|
|
||||||
SetEvent(hCmdReadEvent); /* let read thread get one line */
|
SetEvent(hCmdReadEvent); /* let read thread get one line */
|
||||||
WaitForSingleObject(hCmdReadyEvent, INFINITE); /* wait for read thread or GUI to respond */
|
WaitForSingleObject(hCmdReadyEvent, INFINITE); /* wait for read thread or GUI to respond */
|
||||||
strncpy(ptr, cmdbuffer, MIN(size, sizeof(cmdbuffer))); /* copy line to caller's buffer */
|
strncpy(ptr, cmdbuffer, MIN(size, sizeof(cmdbuffer))); /* copy line to caller's buffer */
|
||||||
|
@ -1564,6 +1596,7 @@ char *read_cmdline (char *ptr, int size, FILE *stream)
|
||||||
|
|
||||||
if (scp_stuffed) { /* stuffed command needs to be echoed */
|
if (scp_stuffed) { /* stuffed command needs to be echoed */
|
||||||
sim_printf("%s\n", cptr);
|
sim_printf("%s\n", cptr);
|
||||||
|
scp_stuffed = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cptr;
|
return cptr;
|
||||||
|
@ -1575,8 +1608,6 @@ void stuff_cmd (char *cmd)
|
||||||
{
|
{
|
||||||
strcpy(cmdbuffer, cmd); /* save the string */
|
strcpy(cmdbuffer, cmd); /* save the string */
|
||||||
scp_stuffed = TRUE; /* note where it came from */
|
scp_stuffed = TRUE; /* note where it came from */
|
||||||
scp_reading = FALSE;
|
|
||||||
ResetEvent(hCmdReadEvent); /* clear read request event */
|
|
||||||
SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */
|
SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1602,8 +1633,6 @@ static void my_yield (void)
|
||||||
|
|
||||||
t_bool stuff_and_wait (char *cmd, int timeout, int delay)
|
t_bool stuff_and_wait (char *cmd, int timeout, int delay)
|
||||||
{
|
{
|
||||||
scp_reading = FALSE;
|
|
||||||
|
|
||||||
stuff_cmd(cmd);
|
stuff_cmd(cmd);
|
||||||
|
|
||||||
while (! scp_reading) {
|
while (! scp_reading) {
|
||||||
|
@ -1635,10 +1664,8 @@ t_bool stuff_and_wait (char *cmd, int timeout, int delay)
|
||||||
|
|
||||||
void remark_cmd (char *remark)
|
void remark_cmd (char *remark)
|
||||||
{
|
{
|
||||||
if (scp_reading) {
|
if (scp_reading)
|
||||||
putchar('\n');
|
sim_printf("\n");
|
||||||
if (sim_log) putc('\n', sim_log);
|
|
||||||
}
|
|
||||||
|
|
||||||
sim_printf("%s\n", remark);
|
sim_printf("%s\n", remark);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue