consoles also allows Emacs to cleanly terminate process groups. */
Lisp_Object Vw32_start_process_share_console;
+/* Control whether create_child cause the process to inherit Emacs'
+ error mode setting. The default is t, to minimize the possibility of
+ subprocesses blocking when accessing unmounted drives. */
+Lisp_Object Vw32_start_process_inherit_error_mode;
+
/* Time to sleep before reading from a subprocess output pipe - this
avoids the inefficiency of frequently reading small amounts of data.
This is primarily necessary for handling DOS processes on Windows 95,
STARTUPINFO start;
SECURITY_ATTRIBUTES sec_attrs;
SECURITY_DESCRIPTOR sec_desc;
+ DWORD flags;
char dir[ MAXPATHLEN ];
if (cp == NULL) abort ();
strcpy (dir, process_dir);
unixtodos_filename (dir);
-
+
+ flags = (!NILP (Vw32_start_process_share_console)
+ ? CREATE_NEW_PROCESS_GROUP
+ : CREATE_NEW_CONSOLE);
+ if (NILP (Vw32_start_process_inherit_error_mode))
+ flags |= CREATE_DEFAULT_ERROR_MODE;
if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE,
- (!NILP (Vw32_start_process_share_console)
- ? CREATE_NEW_PROCESS_GROUP
- : CREATE_NEW_CONSOLE),
- env, dir,
- &start, &cp->procinfo))
+ flags, env, dir, &start, &cp->procinfo))
goto EH_Fail;
cp->pid = (int) cp->procinfo.dwProcessId;
{
char * dllname = RVA_TO_PTR (imports->Name, section, executable);
- if (strcmp (dllname, "cygwin.dll") == 0)
+ /* The exact name of the cygwin dll has changed with
+ various releases, but hopefully this will be reasonably
+ future proof. */
+ if (strncmp (dllname, "cygwin", 6) == 0)
{
*is_cygnus_app = TRUE;
break;
return 0;
}
- /* Wait for input or child death to be signalled. */
start_time = GetTickCount ();
- active = WaitForMultipleObjects (nh + nc, wait_hnd, FALSE, timeout_ms);
+
+ /* Wait for input or child death to be signalled. If user input is
+ allowed, then also accept window messages. */
+ if (FD_ISSET (0, &orfds))
+ active = MsgWaitForMultipleObjects (nh + nc, wait_hnd, FALSE, timeout_ms,
+ QS_ALLINPUT);
+ else
+ active = WaitForMultipleObjects (nh + nc, wait_hnd, FALSE, timeout_ms);
if (active == WAIT_FAILED)
{
processed - otherwise higher numbered channels could be starved. */
do
{
- if (active >= nh)
+ if (active == nh + nc)
+ {
+ /* There are messages in the lisp thread's queue; we must
+ drain the queue now to ensure they are processed promptly,
+ because if we don't do so, we will not be woken again until
+ further messages arrive.
+
+ NB. If ever we allow window message procedures to callback
+ into lisp, we will need to ensure messages are dispatched
+ at a safe time for lisp code to be run (*), and we may also
+ want to provide some hooks in the dispatch loop to cater
+ for modeless dialogs created by lisp (ie. to register
+ window handles to pass to IsDialogMessage).
+
+ (*) Note that MsgWaitForMultipleObjects above is an
+ internal dispatch point for messages that are sent to
+ windows created by this thread. */
+ drain_message_queue ();
+ }
+ else if (active >= nh)
{
cp = cps[active - nh];
}
foreground_window = GetForegroundWindow ();
- if (foreground_window && SetForegroundWindow (cp->hwnd))
+ if (foreground_window)
{
- /* Generate keystrokes as if user had typed Ctrl-Break or
- Ctrl-C. */
- keybd_event (VK_CONTROL, control_scan_code, 0, 0);
- keybd_event (vk_break_code, break_scan_code,
- (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY), 0);
- keybd_event (vk_break_code, break_scan_code,
- (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY)
- | KEYEVENTF_KEYUP, 0);
- keybd_event (VK_CONTROL, control_scan_code, KEYEVENTF_KEYUP, 0);
-
- /* Sleep for a bit to give time for Emacs frame to respond
- to focus change events (if Emacs was active app). */
- Sleep (10);
-
- SetForegroundWindow (foreground_window);
- }
- }
+ /* NT 5.0, and apparently also Windows 98, will not allow
+ a Window to be set to foreground directly without the
+ user's involvement. The workaround is to attach
+ ourselves to the thread that owns the foreground
+ window, since that is the only thread that can set the
+ foreground window. */
+ DWORD foreground_thread, child_thread;
+ foreground_thread =
+ GetWindowThreadProcessId (foreground_window, NULL);
+ if (foreground_thread == GetCurrentThreadId ()
+ || !AttachThreadInput (GetCurrentThreadId (),
+ foreground_thread, TRUE))
+ foreground_thread = 0;
+
+ child_thread = GetWindowThreadProcessId (cp->hwnd, NULL);
+ if (child_thread == GetCurrentThreadId ()
+ || !AttachThreadInput (GetCurrentThreadId (),
+ child_thread, TRUE))
+ child_thread = 0;
+
+ /* Set the foreground window to the child. */
+ if (SetForegroundWindow (cp->hwnd))
+ {
+ /* Generate keystrokes as if user had typed Ctrl-Break or
+ Ctrl-C. */
+ keybd_event (VK_CONTROL, control_scan_code, 0, 0);
+ keybd_event (vk_break_code, break_scan_code,
+ (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY), 0);
+ keybd_event (vk_break_code, break_scan_code,
+ (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY)
+ | KEYEVENTF_KEYUP, 0);
+ keybd_event (VK_CONTROL, control_scan_code,
+ KEYEVENTF_KEYUP, 0);
+
+ /* Sleep for a bit to give time for Emacs frame to respond
+ to focus change events (if Emacs was active app). */
+ Sleep (100);
+
+ SetForegroundWindow (foreground_window);
+ }
+ /* Detach from the foreground and child threads now that
+ the foreground switching is over. */
+ if (foreground_thread)
+ AttachThreadInput (GetCurrentThreadId (),
+ foreground_thread, FALSE);
+ if (child_thread)
+ AttachThreadInput (GetCurrentThreadId (),
+ child_thread, FALSE);
+ }
+ }
/* Ctrl-Break is NT equivalent of SIGINT. */
else if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid))
{
DEFVAR_LISP ("w32-start-process-show-window",
&Vw32_start_process_show_window,
- "When nil, processes started via start-process hide their windows.\n\
+ "When nil, new child processes hide their windows.\n\
When non-nil, they show their window in the method of their choice.");
Vw32_start_process_show_window = Qnil;
DEFVAR_LISP ("w32-start-process-share-console",
&Vw32_start_process_share_console,
- "When nil, processes started via start-process are given a new console.\n\
+ "When nil, new child processes are given a new console.\n\
When non-nil, they share the Emacs console; this has the limitation of\n\
allowing only only DOS subprocess to run at a time (whether started directly\n\
or indirectly by Emacs), and preventing Emacs from cleanly terminating the\n\
otherwise respond to interrupts from Emacs.");
Vw32_start_process_share_console = Qnil;
+ DEFVAR_LISP ("w32-start-process-inherit-error-mode",
+ &Vw32_start_process_inherit_error_mode,
+ "When nil, new child processes revert to the default error mode.\n\
+When non-nil, they inherit their error mode setting from Emacs, which stops\n\
+them blocking when trying to access unmounted drives etc.");
+ Vw32_start_process_inherit_error_mode = Qt;
+
DEFVAR_INT ("w32-pipe-read-delay", &Vw32_pipe_read_delay,
"Forced delay before reading subprocess output.\n\
This is done to improve the buffering of subprocess output, by\n\