> Date: Sun, 15 Jan 2012 20:48:58 +0200 > From: Eli Zaretskii <[email protected]> > Cc: [email protected], [email protected] > > > Date: Sun, 15 Jan 2012 08:28:46 +0800 > > From: Lynn Lin <[email protected]> > > Cc: [email protected], [email protected] > > > > Is that fine you send me a patch to me so I can verify it? > > Thanks very much! > > I will, once I figure out what is the right patch.
Here, can you please try the patch below? 2012-01-21 Eli Zaretskii <[email protected]> Fix failures on MS-Windows when Make's standard handles are invalid. * w32/subproc/sub_proc.c (process_init_fd): Don't dereference pproc if it is a NULL pointer. (process_begin, process_cleanup): Don't try to close pipe handles whose value is INVALID_HANDLE_VALUE. (process_easy): Initialize hIn, hOut, and hErr to INVALID_HANDLE_VALUE. If DuplicateHandle fails with ERROR_INVALID_HANDLE, duplicate a handle for the null device instead of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE or STD_ERROR_HANDLE. Don't try to close pipe handles whose value is INVALID_HANDLE_VALUE. * function.c (windows32_openpipe): Initialize hIn and hErr to INVALID_HANDLE_VALUE. If DuplicateHandle fails with ERROR_INVALID_HANDLE, duplicate a handle for the null device instead of STD_INPUT_HANDLE or STD_ERROR_HANDLE. Fix indentation. Don't try to close handles whose value is INVALID_HANDLE_VALUE. --- w32/subproc/sub_proc.c~0 2010-07-19 13:10:54.000000000 +0300 +++ w32/subproc/sub_proc.c 2012-01-21 17:13:40.419250000 +0200 @@ -336,17 +336,19 @@ process_init_fd(HANDLE stdinh, HANDLE st sub_process *pproc; pproc = malloc(sizeof(*pproc)); - memset(pproc, 0, sizeof(*pproc)); + if (pproc) { + memset(pproc, 0, sizeof(*pproc)); - /* - * Just pass the provided file handles to the 'child side' of the - * pipe, bypassing pipes altogether. - */ - pproc->sv_stdin[1] = (intptr_t) stdinh; - pproc->sv_stdout[1] = (intptr_t) stdouth; - pproc->sv_stderr[1] = (intptr_t) stderrh; + /* + * Just pass the provided file handles to the 'child + * side' of the pipe, bypassing pipes altogether. + */ + pproc->sv_stdin[1] = (intptr_t) stdinh; + pproc->sv_stdout[1] = (intptr_t) stdouth; + pproc->sv_stderr[1] = (intptr_t) stderrh; - pproc->last_err = pproc->lerrno = 0; + pproc->last_err = pproc->lerrno = 0; + } return((HANDLE)pproc); } @@ -585,9 +587,12 @@ process_begin( CloseHandle(procInfo.hThread); /* Close the halves of the pipes we don't need */ - CloseHandle((HANDLE)pproc->sv_stdin[1]); - CloseHandle((HANDLE)pproc->sv_stdout[1]); - CloseHandle((HANDLE)pproc->sv_stderr[1]); + if ((HANDLE)pproc->sv_stdin[1] != INVALID_HANDLE_VALUE) + CloseHandle((HANDLE)pproc->sv_stdin[1]); + if ((HANDLE)pproc->sv_stdout[1] != INVALID_HANDLE_VALUE) + CloseHandle((HANDLE)pproc->sv_stdout[1]); + if ((HANDLE)pproc->sv_stderr[1] != INVALID_HANDLE_VALUE) + CloseHandle((HANDLE)pproc->sv_stderr[1]); pproc->sv_stdin[1] = 0; pproc->sv_stdout[1] = 0; pproc->sv_stderr[1] = 0; @@ -938,11 +943,14 @@ process_cleanup( if (pproc->using_pipes) { for (i= 0; i <= 1; i++) { - if ((HANDLE)pproc->sv_stdin[i]) + if ((HANDLE)pproc->sv_stdin[i] + && (HANDLE)pproc->sv_stdin[i] != INVALID_HANDLE_VALUE) CloseHandle((HANDLE)pproc->sv_stdin[i]); - if ((HANDLE)pproc->sv_stdout[i]) + if ((HANDLE)pproc->sv_stdout[i] + && (HANDLE)pproc->sv_stdout[i] != INVALID_HANDLE_VALUE) CloseHandle((HANDLE)pproc->sv_stdout[i]); - if ((HANDLE)pproc->sv_stderr[i]) + if ((HANDLE)pproc->sv_stderr[i] + && (HANDLE)pproc->sv_stderr[i] != INVALID_HANDLE_VALUE) CloseHandle((HANDLE)pproc->sv_stderr[i]); } } @@ -1207,50 +1215,100 @@ process_easy( char **argv, char **envp) { - HANDLE hIn; - HANDLE hOut; - HANDLE hErr; - HANDLE hProcess; + HANDLE hIn = INVALID_HANDLE_VALUE; + HANDLE hOut = INVALID_HANDLE_VALUE; + HANDLE hErr = INVALID_HANDLE_VALUE; + HANDLE hProcess, tmpIn, tmpOut, tmpErr; + DWORD e; if (proc_index >= MAXIMUM_WAIT_OBJECTS) { DB (DB_JOBS, ("process_easy: All process slots used up\n")); return INVALID_HANDLE_VALUE; } + /* Standard handles returned by GetStdHandle can be NULL or + INVALID_HANDLE_VALUE if the parent process closed them. If that + happens, we open the null device and pass its handle to + CreateProcess as the corresponding handle to inherit. */ + tmpIn = GetStdHandle(STD_INPUT_HANDLE); if (DuplicateHandle(GetCurrentProcess(), - GetStdHandle(STD_INPUT_HANDLE), - GetCurrentProcess(), - &hIn, - 0, - TRUE, - DUPLICATE_SAME_ACCESS) == FALSE) { - fprintf(stderr, - "process_easy: DuplicateHandle(In) failed (e=%ld)\n", - GetLastError()); - return INVALID_HANDLE_VALUE; + tmpIn, + GetCurrentProcess(), + &hIn, + 0, + TRUE, + DUPLICATE_SAME_ACCESS) == FALSE) { + if ((e = GetLastError()) == ERROR_INVALID_HANDLE) { + tmpIn = CreateFile("NUL", GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (tmpIn != INVALID_HANDLE_VALUE + && DuplicateHandle(GetCurrentProcess(), + tmpIn, + GetCurrentProcess(), + &hIn, + 0, + TRUE, + DUPLICATE_SAME_ACCESS) == FALSE) + CloseHandle(tmpIn); + } + if (hIn == INVALID_HANDLE_VALUE) { + fprintf(stderr, "process_easy: DuplicateHandle(In) failed (e=%ld)\n", e); + return INVALID_HANDLE_VALUE; + } } + tmpOut = GetStdHandle (STD_OUTPUT_HANDLE); if (DuplicateHandle(GetCurrentProcess(), - GetStdHandle(STD_OUTPUT_HANDLE), - GetCurrentProcess(), - &hOut, - 0, - TRUE, - DUPLICATE_SAME_ACCESS) == FALSE) { - fprintf(stderr, - "process_easy: DuplicateHandle(Out) failed (e=%ld)\n", - GetLastError()); - return INVALID_HANDLE_VALUE; + tmpOut, + GetCurrentProcess(), + &hOut, + 0, + TRUE, + DUPLICATE_SAME_ACCESS) == FALSE) { + if ((e = GetLastError()) == ERROR_INVALID_HANDLE) { + tmpOut = CreateFile("NUL", GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (tmpOut != INVALID_HANDLE_VALUE + && DuplicateHandle(GetCurrentProcess(), + tmpOut, + GetCurrentProcess(), + &hOut, + 0, + TRUE, + DUPLICATE_SAME_ACCESS) == FALSE) + CloseHandle(tmpOut); + } + if (hOut == INVALID_HANDLE_VALUE) { + fprintf(stderr, "process_easy: DuplicateHandle(Out) failed (e=%ld)\n", e); + return INVALID_HANDLE_VALUE; + } } + tmpErr = GetStdHandle(STD_ERROR_HANDLE); if (DuplicateHandle(GetCurrentProcess(), - GetStdHandle(STD_ERROR_HANDLE), - GetCurrentProcess(), - &hErr, - 0, - TRUE, - DUPLICATE_SAME_ACCESS) == FALSE) { - fprintf(stderr, - "process_easy: DuplicateHandle(Err) failed (e=%ld)\n", - GetLastError()); - return INVALID_HANDLE_VALUE; + tmpErr, + GetCurrentProcess(), + &hErr, + 0, + TRUE, + DUPLICATE_SAME_ACCESS) == FALSE) { + if ((e = GetLastError()) == ERROR_INVALID_HANDLE) { + tmpErr = CreateFile("NUL", GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (tmpErr != INVALID_HANDLE_VALUE + && DuplicateHandle(GetCurrentProcess(), + tmpErr, + GetCurrentProcess(), + &hErr, + 0, + TRUE, + DUPLICATE_SAME_ACCESS) == FALSE) + CloseHandle(tmpErr); + } + if (hErr == INVALID_HANDLE_VALUE) { + fprintf(stderr, "process_easy: DuplicateHandle(Err) failed (e=%ld)\n", e); + return INVALID_HANDLE_VALUE; + } } hProcess = process_init_fd(hIn, hOut, hErr); @@ -1263,9 +1321,12 @@ process_easy( ((sub_process*) hProcess)->exit_code = process_last_err(hProcess); /* close up unused handles */ - CloseHandle(hIn); - CloseHandle(hOut); - CloseHandle(hErr); + if (hIn != INVALID_HANDLE_VALUE) + CloseHandle(hIn); + if (hOut != INVALID_HANDLE_VALUE) + CloseHandle(hOut); + if (hErr != INVALID_HANDLE_VALUE) + CloseHandle(hErr); } process_register(hProcess); --- function.c~0 2010-08-07 11:27:11.981125000 +0300 +++ function.c 2012-01-21 17:23:21.684875000 +0200 @@ -1437,37 +1437,70 @@ void windows32_openpipe (int *pipedes, pid_t *pid_p, char **command_argv, char **envp) { SECURITY_ATTRIBUTES saAttr; - HANDLE hIn; - HANDLE hErr; + HANDLE hIn = INVALID_HANDLE_VALUE; + HANDLE hErr = INVALID_HANDLE_VALUE; HANDLE hChildOutRd; HANDLE hChildOutWr; - HANDLE hProcess; - + HANDLE hProcess, tmpIn, tmpErr; + DWORD e; saAttr.nLength = sizeof (SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; + /* Standard handles returned by GetStdHandle can be NULL or + INVALID_HANDLE_VALUE if the parent process closed them. If that + happens, we open the null device and pass its handle to + process_begin below as the corresponding handle to inherit. */ + tmpIn = GetStdHandle(STD_INPUT_HANDLE); if (DuplicateHandle (GetCurrentProcess(), - GetStdHandle(STD_INPUT_HANDLE), + tmpIn, GetCurrentProcess(), &hIn, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { - fatal (NILF, _("windows32_openpipe(): DuplicateHandle(In) failed (e=%ld)\n"), - GetLastError()); - + if ((e = GetLastError()) == ERROR_INVALID_HANDLE) { + tmpIn = CreateFile("NUL", GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (tmpIn != INVALID_HANDLE_VALUE + && DuplicateHandle(GetCurrentProcess(), + tmpIn, + GetCurrentProcess(), + &hIn, + 0, + TRUE, + DUPLICATE_SAME_ACCESS) == FALSE) + CloseHandle(tmpIn); + } + if (hIn == INVALID_HANDLE_VALUE) + fatal (NILF, _("windows32_openpipe: DuplicateHandle(In) failed (e=%ld)\n"), e); } + tmpErr = GetStdHandle(STD_ERROR_HANDLE); if (DuplicateHandle(GetCurrentProcess(), - GetStdHandle(STD_ERROR_HANDLE), + tmpErr, GetCurrentProcess(), &hErr, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { - fatal (NILF, _("windows32_open_pipe(): DuplicateHandle(Err) failed (e=%ld)\n"), - GetLastError()); + if ((e = GetLastError()) == ERROR_INVALID_HANDLE) { + tmpErr = CreateFile("NUL", GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (tmpErr != INVALID_HANDLE_VALUE + && DuplicateHandle(GetCurrentProcess(), + tmpErr, + GetCurrentProcess(), + &hErr, + 0, + TRUE, + DUPLICATE_SAME_ACCESS) == FALSE) + CloseHandle(tmpErr); + } + if (hErr == INVALID_HANDLE_VALUE) + fatal (NILF, _("windows32_openpipe: DuplicateHandle(Err) failed (e=%ld)\n"), e); } if (!CreatePipe(&hChildOutRd, &hChildOutWr, &saAttr, 0)) @@ -1486,23 +1519,25 @@ windows32_openpipe (int *pipedes, pid_t if (!process_begin(hProcess, command_argv, envp, command_argv[0], NULL)) { /* register process for wait */ - process_register(hProcess); + process_register(hProcess); /* set the pid for returning to caller */ - *pid_p = (pid_t) hProcess; + *pid_p = (pid_t) hProcess; - /* set up to read data from child */ - pipedes[0] = _open_osfhandle((intptr_t) hChildOutRd, O_RDONLY); + /* set up to read data from child */ + pipedes[0] = _open_osfhandle((intptr_t) hChildOutRd, O_RDONLY); - /* this will be closed almost right away */ - pipedes[1] = _open_osfhandle((intptr_t) hChildOutWr, O_APPEND); + /* this will be closed almost right away */ + pipedes[1] = _open_osfhandle((intptr_t) hChildOutWr, O_APPEND); } else { /* reap/cleanup the failed process */ process_cleanup(hProcess); /* close handles which were duplicated, they weren't used */ - CloseHandle(hIn); - CloseHandle(hErr); + if (hIn != INVALID_HANDLE_VALUE) + CloseHandle(hIn); + if (hErr != INVALID_HANDLE_VALUE) + CloseHandle(hErr); /* close pipe handles, they won't be used */ CloseHandle(hChildOutRd); _______________________________________________ Make-w32 mailing list [email protected] https://lists.gnu.org/mailman/listinfo/make-w32
