delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2024/02/03/07:39:57

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: <Zb40A0Fu5NVTHIH4@calimero.vinschen.de>
Mail-Followup-To: cygwin AT cygwin DOT com, David Allsopp <david AT tarides DOT com>
References: <CAJQQdJhzSNZ5dG254g5dv_AuWRxt+R-HLdiCPTkCNv=o+4PVeQ AT mail DOT gmail DOT com>
<ZbtsBD2IKYtH-duQ AT calimero DOT vinschen DOT de>
<CAJQQdJhS3QgJe_KsfGof_6XM6cwtNRkbPQPR32-JaKCu8_8KEA AT mail DOT gmail DOT com>
<ZbzmLRByzmDJxUcb AT calimero DOT vinschen DOT de>
<16b354c2-bba4-40b8-8359-7eb9a79b3ee3 AT dronecode DOT org DOT uk>
<CAJQQdJhYSkjGOFxF=-CnvBGgZa_Qv3HaH8nr8b3fjwqnizq3_Q AT mail DOT gmail DOT com>
<Zbz5TGo_9rqkKMSp AT calimero DOT vinschen DOT de>
<CAJQQdJjurPUo_WfunkkXnraJrP57KUa0gTwSTUwT_mVpKTsLdg AT mail DOT gmail DOT com>
<Zb0k3mRt5_tW5EEB AT calimero DOT vinschen DOT de>
<Zb05sCOey_6hZtzb AT calimero DOT vinschen DOT de>
MIME-Version: 1.0
In-Reply-To: <Zb05sCOey_6hZtzb@calimero.vinschen.de>
X-BeenThere: cygwin AT cygwin DOT com
X-Mailman-Version: 2.1.30
List-Id: General Cygwin discussions and problem reports <cygwin.cygwin.com>
List-Unsubscribe: <https://cygwin.com/mailman/options/cygwin>,
<mailto:cygwin-request AT cygwin DOT com?subject=unsubscribe>
List-Archive: <https://cygwin.com/pipermail/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-request AT cygwin DOT com?subject=help>
List-Subscribe: <https://cygwin.com/mailman/listinfo/cygwin>,
<mailto:cygwin-request AT cygwin DOT com?subject=subscribe>
From: Corinna Vinschen via Cygwin <cygwin AT cygwin DOT com>
Reply-To: cygwin AT cygwin DOT com
Cc: Corinna Vinschen <corinna-cygwin AT cygwin DOT com>
Errors-To: cygwin-bounces+archive-cygwin=delorie DOT com AT cygwin DOT com
Sender: "Cygwin" <cygwin-bounces+archive-cygwin=delorie DOT com AT cygwin DOT com>

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

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019