Browse Source

Promptly close pipe handles passed to child

Parent keeping the handle to write end of child's stdout will
cause ERROR_BROKEN_PIPE not signalled if/when the child exits.

Also add a wrapper for CloseHandle()

Fixes the GUI process hanging in read from child
if the latter unexpectedly dies due to some error.
Trac #1203

Signed-off-by: Selva Nair <selva.nair@gmail.com>
pull/312/head
Selva Nair 5 years ago committed by Gert Doering
parent
commit
5ab2a48ba0
  1. 10
      misc.c
  2. 2
      misc.h
  3. 27
      openvpn.c

10
misc.c

@ -499,3 +499,13 @@ wcs_concat2(WCHAR *dest, int len, const WCHAR *src1, const WCHAR *src2, const WC
n = 0; n = 0;
dest[n] = L'\0'; dest[n] = L'\0';
} }
void
CloseHandleEx(LPHANDLE handle)
{
if (handle && *handle && *handle != INVALID_HANDLE_VALUE)
{
CloseHandle(*handle);
*handle = INVALID_HANDLE_VALUE;
}
}

2
misc.h

@ -44,5 +44,7 @@ BOOL validate_input(const WCHAR *input, const WCHAR *exclude);
/* Concatenate two wide strings with a separator */ /* Concatenate two wide strings with a separator */
void wcs_concat2(WCHAR *dest, int len, const WCHAR *src1, const WCHAR *src2, const WCHAR *sep); void wcs_concat2(WCHAR *dest, int len, const WCHAR *src1, const WCHAR *src2, const WCHAR *sep);
void CloseSemaphore(HANDLE sem); void CloseSemaphore(HANDLE sem);
/* Close a handle if not null or invalid */
void CloseHandleEx(LPHANDLE h);
#endif #endif

27
openvpn.c

@ -2022,6 +2022,9 @@ StartOpenVPN(connection_t *c)
goto out; goto out;
} }
CloseHandleEx(&hStdInRead);
CloseHandleEx(&hNul);
/* Pass management password to OpenVPN process */ /* Pass management password to OpenVPN process */
c->manage.password[sizeof(c->manage.password) - 1] = '\n'; c->manage.password[sizeof(c->manage.password) - 1] = '\n';
WriteFile(hStdInWrite, c->manage.password, sizeof(c->manage.password), &written, NULL); WriteFile(hStdInWrite, c->manage.password, sizeof(c->manage.password), &written, NULL);
@ -2159,8 +2162,8 @@ ReadLineFromStdOut(HANDLE hStdOut, char *line, DWORD size)
BOOL BOOL
CheckVersion() CheckVersion()
{ {
HANDLE hStdOutRead; HANDLE hStdOutRead = NULL;
HANDLE hStdOutWrite; HANDLE hStdOutWrite = NULL;
BOOL retval = FALSE; BOOL retval = FALSE;
STARTUPINFO si; STARTUPINFO si;
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
@ -2217,19 +2220,23 @@ CheckVersion()
si.hStdError = hStdOutWrite; si.hStdError = hStdOutWrite;
/* Start OpenVPN to check version */ /* Start OpenVPN to check version */
if (!CreateProcess(o.exe_path, cmdline, NULL, NULL, TRUE, bool success = CreateProcess(o.exe_path, cmdline, NULL, NULL, TRUE,
CREATE_NO_WINDOW, NULL, pwd, &si, &pi)) CREATE_NO_WINDOW, NULL, pwd, &si, &pi);
if (!success)
{ {
ShowLocalizedMsg(IDS_ERR_CREATE_PROCESS, o.exe_path, cmdline, pwd); ShowLocalizedMsg(IDS_ERR_CREATE_PROCESS, o.exe_path, cmdline, pwd);
goto out;
} }
else if (ReadLineFromStdOut(hStdOutRead, line, sizeof(line)))
CloseHandleEx(&hStdOutWrite);
CloseHandleEx(&pi.hThread);
CloseHandleEx(&pi.hProcess);
if (ReadLineFromStdOut(hStdOutRead, line, sizeof(line)))
{ {
#ifdef DEBUG #ifdef DEBUG
PrintDebug(_T("VersionString: %S"), line); PrintDebug(_T("VersionString: %S"), line);
#endif #endif
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
/* OpenVPN version 2.x */ /* OpenVPN version 2.x */
char *p = strstr(line, match_version); char *p = strstr(line, match_version);
if (p) if (p)
@ -2242,8 +2249,8 @@ CheckVersion()
} }
out: out:
CloseHandle(hStdOutRead); CloseHandleEx(&hStdOutWrite);
CloseHandle(hStdOutWrite); CloseHandleEx(&hStdOutRead);
return retval; return retval;
} }

Loading…
Cancel
Save