X-Recipient: archive-cygwin AT delorie DOT com DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org F0E4C3857C62 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cygwin.com; s=default; t=1706963996; bh=PVrCxWh+FOGyzElJad1zz50zMQSOtyEYTUXGOYKQMx0=; h=Date:To:Subject:References:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=XSrV2DQRC99X/GUGjj6RHmQPCliZUoGVc2Z6aIenJ2fPo4rZBbyzfo7CZwd/Va6c+ DPL1fISmi1xNya2QeK658p0qsCB9wp4nXo4csX4Y6zpxnh2BbgN7y3cUm4/IRLIYJx 3jG2aN+Bb0cTO4y2LPh5RtqAAOWwxEtv6iKsfnEw= X-Original-To: cygwin AT cygwin DOT com Delivered-To: cygwin AT cygwin DOT com DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A5DC93858C42 Date: Sat, 3 Feb 2024 13:39:31 +0100 To: cygwin AT cygwin DOT com Subject: Re: Restore SEM_FAILCRITICALERRORS [was: Aren't Windows System Error popups meant to be disabled in Cygwin?] Message-ID: Mail-Followup-To: cygwin AT cygwin DOT com, David Allsopp References: <16b354c2-bba4-40b8-8359-7eb9a79b3ee3 AT dronecode DOT org DOT uk> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-BeenThere: cygwin AT cygwin DOT com X-Mailman-Version: 2.1.30 Precedence: list List-Id: General Cygwin discussions and problem reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Corinna Vinschen via Cygwin Reply-To: cygwin AT cygwin DOT com Cc: Corinna Vinschen Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: cygwin-bounces+archive-cygwin=delorie DOT com AT cygwin DOT com Sender: "Cygwin" On Feb 2 19:51, Corinna Vinschen via Cygwin wrote: > On Feb 2 18:22, Corinna Vinschen via Cygwin wrote: > > On Feb 2 14:56, David Allsopp via Cygwin wrote: > > > On Fri, 2 Feb 2024 at 14:18, Corinna Vinschen via Cygwin wrote: > > > > Is it actually a safe bet that the error mode set by SetThreadErrorMode > > > > is then propagated as process error mode to the child process? > > > > > > > > I have to ask that because Microsoft conveniently forgot to document > > > > this scenario in the MSDN docs. > > > > > > :o) Never knowingly clear, are they! It would seem to be the intent of > > > SetThreadErrorMode that it would behave that way but who knows. > > > > > > Happy to set up a quick experiment to check that it does work (i.e. > > > [...] > > Wanna try this? > [...] > However, it occured to me that this won't work at all. > [...] Sorry to say that, but SetThreadErrorMode/CreateProcess don't do what we want them to do. I just tested this myself with a modified Cygwin DLL (code below) and it turns out that the child process error mode is the same as the parent's process error mode. Changing the thread error mode from the Cygwin default 3 (aka SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX) to 0 doesn't have any effect. Check the below Cygwin patch and look at output ("gem" is my MingW test app just printing the process error mode retrieved via GetErrorMode): $ ./gem 0 [main] dash 990 child_info_spawn::worker: 1 = SetThreadErrorMode (0, 0) GT:0 GP:3 16158 [main] dash 990 child_info_spawn::worker: 1 = SetThreadErrorMode (3, 0) Error mode 0x3 $ The terrible thing here is the output of the old thread error mode from GetThreadErrorMode as well as from SetThreadErrorMode. MSDN says: Each process has an associated error mode that indicates to the system how the application is going to respond to serious errors. A thread inherits the error mode of the process in which it is running. To retrieve the process error mode, use the GetErrorMode function. To retrieve the error mode of the calling thread, use the GetThreadErrorMode function. What that means is, even though the process error mode is 3 , and even though "A thread inherits the error mode of the process in which it is running", GetThreadErrorMode/SetThreadErrorMode return a thread error code of 0!!! So if GetThreadErrorMode returns 0, you *have* to call GetErrorMode to retrieve the *actual* thread error mode, because the thread error mode just says "yo man, it's default". In extension this probably *also* means, setting the thread error mode to 0 does NOT mean "set it to system default" as MSDN claims, but it means "set it to process default". But in fact, even if I set a non-0 thread error mode, this has no effect on the child process. I forced the thread error mode to 1 before calling CreateProcess, and the resulting child process error mode was still the Cygwin process error mode 3. Isn't that completely screwed up? Ok, my Cygwin DLL test patch follows below. Corinna diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index a40129c22232..14ba4e3769f1 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -718,7 +718,8 @@ dll_crt0_0 () init_windows_system_directory (); initial_env (); - SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); + UINT proc_error_mode = SetErrorMode (SEM_FAILCRITICALERRORS + | SEM_NOGPFAULTERRORBOX); lock_process::init (); user_data->impure_ptr = _impure_ptr; @@ -738,6 +739,13 @@ dll_crt0_0 () if (!child_proc_info) { setup_cygheap (); + /* Memorize the original error mode when this Cygwin process + has been called from a non-Cygwin process. We restore to + this error mode on spawning a non-Cygwin process. This allows + to set a non-default error mode prior to calling the first + Cygwin process and forward it to any subsequent non-Cygwin + child process at spawn time. */ + cygheap->orig_proc_error_mode = proc_error_mode; memory_init (); } else diff --git a/winsup/cygwin/local_includes/cygheap.h b/winsup/cygwin/local_includes/cygheap.h index b6acdf7f18b7..02e3cb4621e3 100644 --- a/winsup/cygwin/local_includes/cygheap.h +++ b/winsup/cygwin/local_includes/cygheap.h @@ -517,6 +517,7 @@ struct init_cygheap: public mini_cygheap mode_t umask; LONG rlim_as_id; unsigned long rlim_core; + UINT orig_proc_error_mode; /* Set when started from non-Cygwin process */ HANDLE console_h; cwdstuff cwd; dtable fdtab; diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 8a2db5cf72e2..85dbec431b28 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -401,13 +401,6 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, c_flags |= CREATE_SEPARATE_WOW_VDM | CREATE_UNICODE_ENVIRONMENT; - /* Add CREATE_DEFAULT_ERROR_MODE flag for non-Cygwin processes so they - get the default error mode instead of inheriting the mode Cygwin - uses. This allows things like Windows Error Reporting/JIT debugging - to work with processes launched from a Cygwin shell. */ - if (!real_path.iscygexec ()) - c_flags |= CREATE_DEFAULT_ERROR_MODE; - /* We're adding the CREATE_BREAKAWAY_FROM_JOB flag here to workaround issues with the "Program Compatibility Assistant (PCA) Service". For some reason, when starting long running sessions from mintty(*), @@ -648,6 +641,17 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, && !::cygheap->user.groups.issetgroups () && !::cygheap->user.setuid_to_restricted)) { + if (!iscygwin ()) + { + UINT old, old2, old3; + BOOL ret; + + old2 = GetThreadErrorMode (); + old3 = GetErrorMode (); + ret = SetThreadErrorMode (cygheap->orig_proc_error_mode, &old); + system_printf ("%d = SetThreadErrorMode (%u, %u) GT:%u GP:%u\r\n", + ret, cygheap->orig_proc_error_mode, old, old2, old3); + } rc = CreateProcessW (runpath, /* image name w/ full path */ cmd.wcs (wcmd), /* what was passed to exec */ sa, /* process security attrs */ @@ -658,6 +662,19 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, NULL, &si, &pi); + if (!iscygwin ()) + { + UINT old; + BOOL ret; + + ret = SetThreadErrorMode (SEM_FAILCRITICALERRORS + | SEM_NOGPFAULTERRORBOX, + &old); + system_printf ("%d = SetThreadErrorMode (%u, %u)\r\n", + ret, + SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX, + old); + } } else { -- Problem reports: https://cygwin.com/problems.html FAQ: https://cygwin.com/faq/ Documentation: https://cygwin.com/docs.html Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple