X-Git-Url: http://winboard.nl/cgi-bin?p=polyglot.git;a=blobdiff_plain;f=pipex_win32.c;h=41431b3a657dcc0a1f5ee7cefc13d44549dc2ea6;hp=8d9e893e43c51808d58e3e8074af8ffe9aba643b;hb=HEAD;hpb=e15efca6667b2673b4c1a5879a6917eab6800e58 diff --git a/pipex_win32.c b/pipex_win32.c index 8d9e893..41431b3 100644 --- a/pipex_win32.c +++ b/pipex_win32.c @@ -59,15 +59,21 @@ static DWORD WINAPI ThreadProc(LPVOID lpParam){ // pipex_open() -void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) { +void pipex_open(pipex_t *pipex, + const char *szName, + const char *szWorkingDir, + const char *szProcFile) { DWORD dwMode, dwThreadId; HANDLE hStdinRead, hStdinWrite, hStdoutRead, hStdoutWrite, hThread; SECURITY_ATTRIBUTES sa; STARTUPINFO si; PROCESS_INFORMATION pi; int fdInput; + char *szCurrentDir; pipex->state=0; pipex->name=szName; + pipex->command=szProcFile; + pipex->quit_pending=FALSE; pipex->hProcess=NULL; if (szProcFile == NULL) { pipex->hInput = GetStdHandle(STD_INPUT_HANDLE); @@ -88,7 +94,15 @@ void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) { si.hStdInput = hStdinRead; si.hStdOutput = hStdoutWrite; si.hStdError = hStdoutWrite; - if(CreateProcess(NULL, + if((szCurrentDir = (char*)_getcwd( NULL, 0 )) == NULL ) + my_fatal("pipex_open(): no current directory: %s\n", + strerror(errno)); + if(_chdir(szWorkingDir)){ + my_fatal("pipex_open(): %s: %s\n", + szWorkingDir, + strerror(errno)); + } + if(CreateProcess(NULL, (LPSTR) szProcFile, NULL, NULL, @@ -107,8 +121,9 @@ void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) { pipex->bConsole = FALSE; pipex->bPipe=TRUE; }else{ - my_fatal("pipex_open(): %s",win32_error()); + my_fatal("pipex_open(): %s: %s",szProcFile,win32_error()); } + _chdir(szCurrentDir); } if (pipex->bConsole) { SetConsoleMode(pipex->hInput, @@ -144,9 +159,11 @@ void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) { if(!hThread){ my_fatal("pipex_open(): %s",win32_error()); } + pipex->dwWriteIndex=0; pipex_set_active(pipex); } + // pipex_wait_event(pipex) void pipex_wait_event(pipex_t *pipex[]){ @@ -167,7 +184,6 @@ void pipex_wait_event(pipex_t *pipex[]){ ); } - // pipex_send_eof() void pipex_send_eof(pipex_t *pipex) { @@ -177,17 +193,47 @@ void pipex_send_eof(pipex_t *pipex) { // pipex_exit() -void pipex_exit(pipex_t *pipex) { +/* This routine waits for kill_timeout milliseconds for + * the process to exit by itself. If that doesn't + * happen it will kill the process. + */ + +void pipex_exit(pipex_t *pipex, int kill_timeout) { + DWORD lpexit; + int elapsed_time; + bool exited; CloseHandle(pipex->hInput); CloseHandle(pipex->hOutput); - DWORD lpexit; - - if(GetExitCodeProcess(pipex->hProcess,&lpexit)){ - if(lpexit==STILL_ACTIVE) - //must be java,hammer it down! - TerminateProcess(pipex->hProcess,lpexit); + // ExitProcess(pipex->hProcess,0); + + my_log("POLYGLOT Waiting for child process to exit.\n"); + elapsed_time=0; + exited=FALSE; + + while(elapsed_timehProcess,&lpexit); + if(lpexit==STILL_ACTIVE){ + my_log("POLYGLOT Child has not exited yet. Sleeping %dms.\n", WAIT_GRANULARITY); + my_sleep(WAIT_GRANULARITY); + elapsed_time+=WAIT_GRANULARITY; + }else{ + exited=TRUE; + break; + } + } + + if(!exited){ + my_log("POLYGLOT Child wouldn't exit by itself. Terminating it.\n"); + TerminateProcess(pipex->hProcess,lpexit); + } + CloseHandle(pipex->hProcess); + + if(!pipex->quit_pending){ + // suppress further errors + pipex->quit_pending=TRUE; + my_fatal("pipex_exit(): %s: child exited unexpectedly.\n",pipex->command); } - CloseHandle(pipex->hProcess); + } // pipex_eof_input() @@ -206,10 +252,7 @@ static void pipex_set_eof_input(pipex_t *pipex){ EnterCriticalSection(&(pipex->CriticalSection)); (pipex->state)|=PIPEX_EOF; LeaveCriticalSection(&(pipex->CriticalSection)); - // not quit the right place - my_log("%s->Adapter: EOF\n",pipex->name); - -} + } // pipex_active() @@ -322,6 +365,8 @@ bool pipex_eof(pipex_t *pipex){ bool pipex_readln_nb(pipex_t *pipex, char *szLineStr) { int nFeedEnd; int ret; + int src, dst; + char c; EnterCriticalSection(&(pipex->CriticalSection)); if ((pipex->lpFeedEnd) == NULL) { ret=FALSE; @@ -329,10 +374,18 @@ bool pipex_readln_nb(pipex_t *pipex, char *szLineStr) { nFeedEnd = pipex->lpFeedEnd - pipex->lpBuffer; memcpy(szLineStr, pipex->lpBuffer, nFeedEnd+1); szLineStr[nFeedEnd] = '\0'; - // temp hack: we use the fact that strtok modifies its first argument - strtok(szLineStr,"\r\n"); + + // temp hack: stolen from util.c + // remove CRs and LFs + src = 0; + dst = 0; + while ((c=szLineStr[src++]) != '\0') { + if (c != '\r' && c != '\n') szLineStr[dst++] = c; + } + szLineStr[dst] = '\0'; ASSERT(strchr(szLineStr,'\n')==NULL) ASSERT(strchr(szLineStr,'\r')==NULL) + nFeedEnd ++; pipex->nReadEnd -= nFeedEnd; memcpy(pipex->lpBuffer, pipex->lpBuffer + nFeedEnd, pipex->nReadEnd+1); @@ -372,6 +425,7 @@ bool pipex_readln(pipex_t *pipex, char *szLineStr) { WaitForSingleObject(pipex->hEvent,INFINITE); } } + my_log("%s->Adapter: EOF\n",pipex->name); szLineStr[0]='\0'; return FALSE; } @@ -408,12 +462,13 @@ void pipex_set_priority(pipex_t *pipex, int value){ // pipex_set_affinit() +typedef void (WINAPI *SPAM)(HANDLE, int); void pipex_set_affinity(pipex_t *pipex, int value){ + SPAM pSPAM; + if(pipex->hProcess) return; if(value==-1) return; - typedef void (WINAPI *SPAM)(HANDLE, int); - SPAM pSPAM; pSPAM = (SPAM) GetProcAddress( GetModuleHandle(TEXT("kernel32.dll")), "SetProcessAffinityMask"); @@ -425,22 +480,50 @@ void pipex_set_affinity(pipex_t *pipex, int value){ } } +// pipex_write() + +void pipex_write(pipex_t *pipex, const char *szLineStr) { + int size,written; + size=sizeof(pipex->szWriteBuffer)-pipex->dwWriteIndex; + written=snprintf(pipex->szWriteBuffer + pipex->dwWriteIndex, + size, + "%s", + szLineStr); + // snprintf returns how many bytes should have been written + // (not including the trailing zero) + // old versions of glibc and msvcrt return -1 in + // case of truncated output. + if(written>=size || written<0){ + my_fatal("engine_send(): write_buffer overflow\n"); + } + pipex->dwWriteIndex+=written; + +} + + // pipex_writeln() void pipex_writeln(pipex_t *pipex, const char *szLineStr) { DWORD dwBytes; - int nStrLen; - char szWriteBuffer[LINE_INPUT_MAX_CHAR]; - my_log("Adapter->%s: %s\n",pipex->name,szLineStr); + DWORD dwLengthWriteBuffer; + pipex_write(pipex, szLineStr); + my_log("Adapter->%s: %s\n",pipex->name,pipex->szWriteBuffer); if(pipex->bPipe){ - nStrLen = strlen(szLineStr); - memcpy(szWriteBuffer, szLineStr, nStrLen); - szWriteBuffer[nStrLen] = '\r'; - szWriteBuffer[nStrLen + 1] = '\n'; - WriteFile(pipex->hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL); + dwLengthWriteBuffer = strlen(pipex->szWriteBuffer); + if(dwLengthWriteBuffer>=sizeof(pipex->szWriteBuffer)-3){ + my_fatal("pipex_writeln(): write buffer overflow\n"); + } + pipex->szWriteBuffer[dwLengthWriteBuffer] = '\r'; + pipex->szWriteBuffer[dwLengthWriteBuffer + 1] = '\n'; + // for easy debugging + pipex->szWriteBuffer[dwLengthWriteBuffer + 2] = '\0'; + WriteFile(pipex->hOutput, pipex->szWriteBuffer, + dwLengthWriteBuffer + 2, + &dwBytes, NULL); }else{ - printf("%s\n",szLineStr); + printf("%s\n",pipex->szWriteBuffer); fflush(stdout); } + pipex->dwWriteIndex = 0; } #endif