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:
Mark Pizzolato 2017-05-07 18:56:48 -07:00
parent 0c27d1f5a8
commit b866f76af7

View file

@ -1523,21 +1523,54 @@ static HANDLE hCmdReadEvent = NULL;
static HANDLE hCmdReadyEvent = NULL;
static BOOL scp_stuffed = FALSE, scp_reading = FALSE;
static char cmdbuffer[256];
static BOOL read_exiting = FALSE;
/* CmdThread - separate thread to read commands from stdin upon request */
static DWORD WINAPI CmdThread (LPVOID arg)
{
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
DWORD dwBytesRead;
for (;;) {
WaitForSingleObject(hCmdReadEvent, INFINITE); /* wait for request */
read_line(cmdbuffer, sizeof(cmdbuffer), stdin); /* read one line */
scp_stuffed = FALSE; /* say how we got it */
scp_reading = FALSE;
SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */
if (WAIT_TIMEOUT == WaitForSingleObject(hCmdReadEvent, 2000)) /* wait for request */
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_reading = FALSE;
SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */
} else {
DWORD dwError = GetLastError();
scp_reading = FALSE;
}
}
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 *cptr;
@ -1551,10 +1584,9 @@ char *read_cmdline (char *ptr, int size, FILE *stream)
/* start up the command thread */
if ((hCmdThread = CreateThread(NULL, 0, CmdThread, NULL, 0, &iCmdThreadID)) == NULL)
scp_panic("Unable to create command line reading thread");
atexit(read_atexit);
}
scp_reading = TRUE;
SetEvent(hCmdReadEvent); /* let read thread get one line */
WaitForSingleObject(hCmdReadyEvent, INFINITE); /* wait for read thread or GUI to respond */
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 */
sim_printf("%s\n", cptr);
scp_stuffed = FALSE;
}
return cptr;
@ -1575,8 +1608,6 @@ void stuff_cmd (char *cmd)
{
strcpy(cmdbuffer, cmd); /* save the string */
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 */
}
@ -1602,8 +1633,6 @@ static void my_yield (void)
t_bool stuff_and_wait (char *cmd, int timeout, int delay)
{
scp_reading = FALSE;
stuff_cmd(cmd);
while (! scp_reading) {
@ -1635,10 +1664,8 @@ t_bool stuff_and_wait (char *cmd, int timeout, int delay)
void remark_cmd (char *remark)
{
if (scp_reading) {
putchar('\n');
if (sim_log) putc('\n', sim_log);
}
if (scp_reading)
sim_printf("\n");
sim_printf("%s\n", remark);