Cygwin: pty: Add error handling in setup_pseudoconsole().

- In setup_pseudoconsole(), many error handling was omitted. This
  patch adds missing error handling.
This commit is contained in:
Takashi Yano 2020-02-11 02:45:14 +09:00 committed by Corinna Vinschen
parent 9b51beeb2a
commit 8cb20fa5d3
1 changed files with 111 additions and 68 deletions

View File

@ -3413,7 +3413,10 @@ fhandler_pty_master::setup_pseudoconsole ()
process in a pseudo console and get them from the helper. process in a pseudo console and get them from the helper.
Slave process will attach to the pseudo console in the Slave process will attach to the pseudo console in the
helper process using AttachConsole(). */ helper process using AttachConsole(). */
COORD size = {80, 25}; COORD size = {
(SHORT) get_ttyp ()->winsize.ws_col,
(SHORT) get_ttyp ()->winsize.ws_row
};
CreatePipe (&from_master, &to_slave, &sec_none, 0); CreatePipe (&from_master, &to_slave, &sec_none, 0);
SetLastError (ERROR_SUCCESS); SetLastError (ERROR_SUCCESS);
HRESULT res = CreatePseudoConsole (size, from_master, to_master, HRESULT res = CreatePseudoConsole (size, from_master, to_master,
@ -3423,12 +3426,7 @@ fhandler_pty_master::setup_pseudoconsole ()
if (res != S_OK) if (res != S_OK)
system_printf ("CreatePseudoConsole() failed. %08x\n", system_printf ("CreatePseudoConsole() failed. %08x\n",
GetLastError ()); GetLastError ());
CloseHandle (from_master); goto fallback;
CloseHandle (to_slave);
from_master = from_master_cyg;
to_slave = NULL;
get_ttyp ()->h_pseudo_console = NULL;
return false;
} }
/* If master process is running as service, attaching to /* If master process is running as service, attaching to
@ -3439,69 +3437,82 @@ fhandler_pty_master::setup_pseudoconsole ()
if (is_running_as_service ()) if (is_running_as_service ())
get_ttyp ()->attach_pcon_in_fork = true; get_ttyp ()->attach_pcon_in_fork = true;
SIZE_T bytesRequired;
InitializeProcThreadAttributeList (NULL, 2, 0, &bytesRequired);
STARTUPINFOEXW si_helper; STARTUPINFOEXW si_helper;
ZeroMemory (&si_helper, sizeof (si_helper)); HANDLE hello, goodbye;
si_helper.StartupInfo.cb = sizeof (STARTUPINFOEXW);
si_helper.lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)
HeapAlloc (GetProcessHeap (), 0, bytesRequired);
InitializeProcThreadAttributeList (si_helper.lpAttributeList,
2, 0, &bytesRequired);
UpdateProcThreadAttribute (si_helper.lpAttributeList,
0,
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
get_ttyp ()->h_pseudo_console,
sizeof (get_ttyp ()->h_pseudo_console),
NULL, NULL);
HANDLE hello = CreateEvent (&sec_none, true, false, NULL);
HANDLE goodbye = CreateEvent (&sec_none, true, false, NULL);
/* Create a pipe for receiving pseudo console handles */
HANDLE hr, hw; HANDLE hr, hw;
CreatePipe (&hr, &hw, &sec_none, 0);
/* Inherit only handles which are needed by helper. */
HANDLE handles_to_inherit[] = {hello, goodbye, hw};
UpdateProcThreadAttribute (si_helper.lpAttributeList,
0,
PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
handles_to_inherit,
sizeof (handles_to_inherit),
NULL, NULL);
/* Create helper process */
WCHAR cmd[MAX_PATH];
path_conv helper ("/bin/cygwin-console-helper.exe");
size_t len = helper.get_wide_win32_path_len ();
helper.get_wide_win32_path (cmd);
__small_swprintf (cmd + len, L" %p %p %p", hello, goodbye, hw);
si_helper.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
si_helper.StartupInfo.hStdInput = NULL;
si_helper.StartupInfo.hStdOutput = NULL;
si_helper.StartupInfo.hStdError = NULL;
PROCESS_INFORMATION pi_helper; PROCESS_INFORMATION pi_helper;
CreateProcessW (NULL, cmd, &sec_none, &sec_none,
TRUE, EXTENDED_STARTUPINFO_PRESENT,
NULL, NULL, &si_helper.StartupInfo, &pi_helper);
WaitForSingleObject (hello, INFINITE);
CloseHandle (hello);
CloseHandle (pi_helper.hThread);
/* Retrieve pseudo console handles */
DWORD rLen;
char buf[64];
ReadFile (hr, buf, sizeof (buf), &rLen, NULL);
buf[rLen] = '\0';
HANDLE hpConIn, hpConOut; HANDLE hpConIn, hpConOut;
sscanf (buf, "StdHandles=%p,%p", &hpConIn, &hpConOut); {
DuplicateHandle (pi_helper.hProcess, hpConIn, SIZE_T bytesRequired;
GetCurrentProcess (), &hpConIn, 0, InitializeProcThreadAttributeList (NULL, 2, 0, &bytesRequired);
TRUE, DUPLICATE_SAME_ACCESS); ZeroMemory (&si_helper, sizeof (si_helper));
DuplicateHandle (pi_helper.hProcess, hpConOut, si_helper.StartupInfo.cb = sizeof (STARTUPINFOEXW);
GetCurrentProcess (), &hpConOut, 0, si_helper.lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)
TRUE, DUPLICATE_SAME_ACCESS); HeapAlloc (GetProcessHeap (), 0, bytesRequired);
CloseHandle (hr); if (si_helper.lpAttributeList == NULL)
CloseHandle (hw); goto cleanup_pseudo_console;
/* Clean up */ if (!InitializeProcThreadAttributeList (si_helper.lpAttributeList,
DeleteProcThreadAttributeList (si_helper.lpAttributeList); 2, 0, &bytesRequired))
HeapFree (GetProcessHeap (), 0, si_helper.lpAttributeList); goto cleanup_heap;
if (!UpdateProcThreadAttribute (si_helper.lpAttributeList,
0,
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
get_ttyp ()->h_pseudo_console,
sizeof (get_ttyp ()->h_pseudo_console),
NULL, NULL))
goto cleanup_heap;
/* Create events for start/stop helper process. */
hello = CreateEvent (&sec_none, true, false, NULL);
goodbye = CreateEvent (&sec_none, true, false, NULL);
/* Create a pipe for receiving pseudo console handles */
CreatePipe (&hr, &hw, &sec_none, 0);
/* Inherit only handles which are needed by helper. */
HANDLE handles_to_inherit[] = {hello, goodbye, hw};
if (!UpdateProcThreadAttribute (si_helper.lpAttributeList,
0,
PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
handles_to_inherit,
sizeof (handles_to_inherit),
NULL, NULL))
goto cleanup_event_and_pipes;
/* Create helper process */
WCHAR cmd[MAX_PATH];
path_conv helper ("/bin/cygwin-console-helper.exe");
size_t len = helper.get_wide_win32_path_len ();
helper.get_wide_win32_path (cmd);
__small_swprintf (cmd + len, L" %p %p %p", hello, goodbye, hw);
si_helper.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
si_helper.StartupInfo.hStdInput = NULL;
si_helper.StartupInfo.hStdOutput = NULL;
si_helper.StartupInfo.hStdError = NULL;
if (!CreateProcessW (NULL, cmd, &sec_none, &sec_none,
TRUE, EXTENDED_STARTUPINFO_PRESENT,
NULL, NULL, &si_helper.StartupInfo, &pi_helper))
goto cleanup_event_and_pipes;
WaitForSingleObject (hello, INFINITE);
CloseHandle (hello);
CloseHandle (pi_helper.hThread);
/* Retrieve pseudo console handles */
DWORD rLen;
char buf[64];
if (!ReadFile (hr, buf, sizeof (buf), &rLen, NULL))
goto cleanup_helper_process;
buf[rLen] = '\0';
sscanf (buf, "StdHandles=%p,%p", &hpConIn, &hpConOut);
if (!DuplicateHandle (pi_helper.hProcess, hpConIn,
GetCurrentProcess (), &hpConIn, 0,
TRUE, DUPLICATE_SAME_ACCESS))
goto cleanup_helper_process;
if (!DuplicateHandle (pi_helper.hProcess, hpConOut,
GetCurrentProcess (), &hpConOut, 0,
TRUE, DUPLICATE_SAME_ACCESS))
goto cleanup_pcon_in;
CloseHandle (hr);
CloseHandle (hw);
/* Clean up */
DeleteProcThreadAttributeList (si_helper.lpAttributeList);
HeapFree (GetProcessHeap (), 0, si_helper.lpAttributeList);
}
/* Setting information of stuffs regarding pseudo console */ /* Setting information of stuffs regarding pseudo console */
get_ttyp ()->h_helper_goodbye = goodbye; get_ttyp ()->h_helper_goodbye = goodbye;
get_ttyp ()->h_helper_process = pi_helper.hProcess; get_ttyp ()->h_helper_process = pi_helper.hProcess;
@ -3510,7 +3521,38 @@ fhandler_pty_master::setup_pseudoconsole ()
CloseHandle (to_master); CloseHandle (to_master);
from_master = hpConIn; from_master = hpConIn;
to_master = hpConOut; to_master = hpConOut;
ResizePseudoConsole (get_ttyp ()->h_pseudo_console, size);
return true; return true;
cleanup_pcon_in:
CloseHandle (hpConIn);
cleanup_helper_process:
SetEvent (goodbye);
WaitForSingleObject (pi_helper.hProcess, INFINITE);
CloseHandle (pi_helper.hProcess);
goto skip_close_hello;
cleanup_event_and_pipes:
CloseHandle (hello);
skip_close_hello:
CloseHandle (goodbye);
CloseHandle (hr);
CloseHandle (hw);
cleanup_heap:
HeapFree (GetProcessHeap (), 0, si_helper.lpAttributeList);
cleanup_pseudo_console:
{
HPCON_INTERNAL *hp = (HPCON_INTERNAL *) get_ttyp ()->h_pseudo_console;
HANDLE tmp = hp->hConHostProcess;
ClosePseudoConsole (get_pseudo_console ());
CloseHandle (tmp);
}
fallback:
CloseHandle (from_master);
CloseHandle (to_slave);
from_master = from_master_cyg;
to_slave = NULL;
get_ttyp ()->h_pseudo_console = NULL;
return false;
} }
bool bool
@ -3629,14 +3671,15 @@ fhandler_pty_master::setup ()
} }
get_ttyp ()->fwd_done = CreateEvent (&sec_none, true, false, NULL); get_ttyp ()->fwd_done = CreateEvent (&sec_none, true, false, NULL);
t.winsize.ws_col = 80;
t.winsize.ws_row = 25;
setup_pseudoconsole (); setup_pseudoconsole ();
t.set_from_master (from_master); t.set_from_master (from_master);
t.set_from_master_cyg (from_master_cyg); t.set_from_master_cyg (from_master_cyg);
t.set_to_master (to_master); t.set_to_master (to_master);
t.set_to_master_cyg (to_master_cyg); t.set_to_master_cyg (to_master_cyg);
t.winsize.ws_col = 80;
t.winsize.ws_row = 25;
t.master_pid = myself->pid; t.master_pid = myself->pid;
dev ().parse (DEV_PTYM_MAJOR, unit); dev ().parse (DEV_PTYM_MAJOR, unit);