aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin/fhandler/console.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/fhandler/console.cc')
-rw-r--r--winsup/cygwin/fhandler/console.cc162
1 files changed, 112 insertions, 50 deletions
diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc
index 1c0d5c8..d4c3f10 100644
--- a/winsup/cygwin/fhandler/console.cc
+++ b/winsup/cygwin/fhandler/console.cc
@@ -33,6 +33,7 @@ details. */
#include "child_info.h"
#include "cygwait.h"
#include "winf.h"
+#include "psapi.h"
/* Don't make this bigger than NT_MAX_PATH as long as the temporary buffer
is allocated using tmp_pathbuf!!! */
@@ -48,6 +49,9 @@ details. */
con.b.srWindow.Top + con.scroll_region.Bottom)
#define con_is_legacy (shared_console_info[unit] && con.is_legacy)
+static HANDLE NO_COPY shared_info_mutex;
+static int NO_COPY shared_info_state[MAX_CONS_DEV];
+
#define CONS_THREAD_SYNC "cygcons.thread_sync"
static bool NO_COPY master_thread_started = false;
@@ -224,44 +228,52 @@ fhandler_console::open_shared_console (HWND hw, HANDLE& h, bool& created)
return res;
}
-BOOL CALLBACK
-fhandler_console::enum_windows (HWND hw, LPARAM lp)
+fhandler_console::console_unit::console_unit (int n0, HANDLE *input_mutex) :
+ n (-1)
{
- console_unit *this1 = (console_unit *) lp;
- HANDLE h = NULL;
- fhandler_console::console_state *cs;
- if ((cs = fhandler_console::open_shared_console (hw, h)))
+ char buf[MAX_PATH];
+ for (int i = max(0, n0); i < MAX_CONS_DEV; i++)
{
- CloseHandle (h);
- if (major (cs->tty_min_state.getntty ()) == DEV_CONS_MAJOR)
- this1->bitmask |= 1UL << minor (cs->tty_min_state.getntty ());
- if (this1->n == minor (cs->tty_min_state.getntty ()))
+ shared_name (buf, "cygcons.input.mutex", i);
+ SetLastError (ERROR_SUCCESS);
+ HANDLE input_mutex0 = CreateMutex (&sec_none, FALSE, buf);
+ DWORD err = GetLastError ();
+ if (err == ERROR_ALREADY_EXISTS || err == ERROR_ACCESS_DENIED)
{
- this1->shared_console_info = cs;
- return FALSE;
+ if (n0 >= 0)
+ n = i;
}
- UnmapViewOfFile ((void *) cs);
+ else if (n0 == CONS_SCAN_UNUSED)
+ {
+ n = i;
+ if (input_mutex)
+ *input_mutex = input_mutex0;
+ break;
+ }
+ if (input_mutex0)
+ CloseHandle (input_mutex0);
+ if (n0 >= 0)
+ break;
}
- else
- { /* Only for ConEmu */
- char class_hw[32];
- if (19 == GetClassName (hw, class_hw, sizeof (class_hw))
- && 0 == strcmp (class_hw, "VirtualConsoleClass"))
- EnumChildWindows (hw, fhandler_console::enum_windows, lp);
+ if (n0 == CONS_SCAN_UNUSED && n < 0)
+ {
+ __small_sprintf (buf, "console device allocation failure - "
+ "too many consoles in use, max consoles is %d",
+ MAX_CONS_DEV);
+ api_fatal (buf);
}
- return TRUE;
}
-fhandler_console::console_unit::console_unit (int n0):
- n (n0), bitmask (0), shared_console_info (NULL)
+fhandler_console::console_unit::operator console_state * () const
{
- EnumWindows (fhandler_console::enum_windows, (LPARAM) this);
- if (n0 == CONS_SCAN_UNUSED && (n = ffsl (~bitmask) - 1) < 0)
- api_fatal (sizeof (bitmask) == 8 ?
- "console device allocation failure - "
- "too many consoles in use, max consoles is 64" :
- "console device allocation failure - "
- "too many consoles in use, max consoles is 32");
+ if (n < 0 || n >= MAX_CONS_DEV)
+ return NULL;
+ HANDLE h = NULL;
+ fhandler_console::console_state *cs;
+ HWND hw = cygwin_shared->cons_hwnd[n];
+ if ((cs = fhandler_console::open_shared_console (hw, h)))
+ CloseHandle (h);
+ return cs;
}
static DWORD
@@ -272,17 +284,23 @@ cons_master_thread (VOID *arg)
fhandler_console::handle_set_t handle_set;
fh->get_duplicated_handle_set (&handle_set);
HANDLE thread_sync_event;
- DuplicateHandle (GetCurrentProcess (), fh->thread_sync_event,
- GetCurrentProcess (), &thread_sync_event,
- 0, FALSE, DUPLICATE_SAME_ACCESS);
- SetEvent (thread_sync_event);
- master_thread_started = true;
- /* Do not touch class members after here because the class instance
- may have been destroyed. */
- fhandler_console::cons_master_thread (&handle_set, ttyp);
- fhandler_console::close_handle_set (&handle_set);
- SetEvent (thread_sync_event);
- CloseHandle (thread_sync_event);
+ if (DuplicateHandle (GetCurrentProcess (), fh->thread_sync_event,
+ GetCurrentProcess (), &thread_sync_event,
+ 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ SetEvent (thread_sync_event);
+ master_thread_started = true;
+ /* Do not touch class members after here because the class instance
+ may have been destroyed. */
+ fhandler_console::cons_master_thread (&handle_set, ttyp);
+ fhandler_console::close_handle_set (&handle_set);
+ SetEvent (thread_sync_event);
+ CloseHandle (thread_sync_event);
+ master_thread_started = false;
+ }
+ else
+ debug_printf ("cons_master_thread not started because thread_sync_event "
+ "could not be duplicated %08x", GetLastError ());
return 0;
}
@@ -451,6 +469,8 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
case WAIT_CANCELED:
break;
default: /* Error */
+ free (input_rec);
+ free (input_tmp);
ReleaseMutex (p->input_mutex);
return;
}
@@ -650,6 +670,11 @@ fhandler_console::set_unit ()
else if (myself->ctty != CTTY_UNINITIALIZED)
unit = device::minor (myself->ctty);
+ if (!shared_info_mutex)
+ shared_info_mutex = CreateMutex (&sec_none_nih, FALSE, NULL);
+
+ WaitForSingleObject (shared_info_mutex, INFINITE);
+
if (shared_console_info[unit])
; /* Do nothing */
else if (generic_console
@@ -658,7 +683,10 @@ fhandler_console::set_unit ()
else
{
if (!generic_console && (dev_t) myself->ctty != get_device ())
- shared_console_info[unit] = console_unit (unit);
+ {
+ shared_console_info[unit] = console_unit (unit);
+ shared_info_state[unit]++;
+ }
if (generic_console || !shared_console_info[unit])
{
me = GetConsoleWindow ();
@@ -669,10 +697,12 @@ fhandler_console::set_unit ()
created = true;
fhandler_console::console_state *cs =
open_shared_console (me, cygheap->console_h, created);
+ shared_info_state[unit]++;
ProtectHandleINH (cygheap->console_h);
if (created)
{
- unit = console_unit (CONS_SCAN_UNUSED);
+ unit = console_unit (CONS_SCAN_UNUSED, &input_mutex);
+ cygwin_shared->cons_hwnd[unit] = me;
cs->tty_min_state.setntty (DEV_CONS_MAJOR, unit);
}
else
@@ -683,6 +713,8 @@ fhandler_console::set_unit ()
}
}
}
+ ReleaseMutex (shared_info_mutex);
+
if (shared_console_info[unit])
{
devset = (fh_devices) shared_console_info[unit]->tty_min_state.getntty ();
@@ -1847,9 +1879,15 @@ fhandler_console::open (int flags, mode_t)
char name[MAX_PATH];
shared_name (name, CONS_THREAD_SYNC, get_minor ());
thread_sync_event = CreateEvent(NULL, FALSE, FALSE, name);
- new cygthread (::cons_master_thread, this, "consm");
- WaitForSingleObject (thread_sync_event, INFINITE);
- CloseHandle (thread_sync_event);
+ if (thread_sync_event)
+ {
+ new cygthread (::cons_master_thread, this, "consm");
+ WaitForSingleObject (thread_sync_event, INFINITE);
+ CloseHandle (thread_sync_event);
+ }
+ else
+ debug_printf ("Failed to create thread_sync_event %08x",
+ GetLastError ());
}
return 1;
}
@@ -1910,9 +1948,15 @@ fhandler_console::close ()
char name[MAX_PATH];
shared_name (name, CONS_THREAD_SYNC, get_minor ());
thread_sync_event = OpenEvent (MAXIMUM_ALLOWED, FALSE, name);
- con.owner = MAX_PID + 1;
- WaitForSingleObject (thread_sync_event, INFINITE);
- CloseHandle (thread_sync_event);
+ if (thread_sync_event)
+ {
+ con.owner = MAX_PID + 1;
+ WaitForSingleObject (thread_sync_event, INFINITE);
+ CloseHandle (thread_sync_event);
+ }
+ else
+ debug_printf ("Failed to open thread_sync_event %08x",
+ GetLastError ());
}
con.owner = 0;
}
@@ -1927,7 +1971,23 @@ fhandler_console::close ()
if (!have_execed && !invisible_console
&& (!CTTY_IS_VALID (myself->ctty)
|| get_device () == (dev_t) myself->ctty))
- free_console ();
+ {
+ /* ConEmu hack. Detach from ConEmu to unhook console APIs. */
+ HMODULE h = GetModuleHandle ("ConEmuHk64.dll");
+ if (h)
+ {
+ MODULEINFO mi;
+ if (GetModuleInformation (GetCurrentProcess (), h, &mi, sizeof (mi)))
+ {
+ BOOL (*DllMain)(HINSTANCE, DWORD, LPVOID) =
+ (BOOL (*)(HINSTANCE, DWORD, LPVOID)) mi.EntryPoint;
+ DllMain (h, DLL_PROCESS_DETACH, NULL);
+ }
+ }
+
+ /* Freeing console to detach the process from the console. */
+ free_console ();
+ }
release_output_mutex ();
@@ -1936,11 +1996,13 @@ fhandler_console::close ()
CloseHandle (output_mutex);
output_mutex = NULL;
- if (shared_console_info[unit] && myself->ctty != tc ()->ntty)
+ WaitForSingleObject (shared_info_mutex, INFINITE);
+ if (--shared_info_state[unit] == 0 && shared_console_info[unit])
{
UnmapViewOfFile ((void *) shared_console_info[unit]);
shared_console_info[unit] = NULL;
}
+ ReleaseMutex (shared_info_mutex);
return 0;
}