diff options
| author | Corinna Vinschen <corinna@vinschen.de> | 2026-01-26 10:13:08 +0100 |
|---|---|---|
| committer | Corinna Vinschen <corinna@vinschen.de> | 2026-01-26 10:13:08 +0100 |
| commit | ab4d1afb5e1e9959e591a6f5f87cdf8c57560c55 (patch) | |
| tree | f4660ba0e40e6273cefb5244309793533f52d044 /newlib/libc/include/assert.h | |
| parent | 8ba4275b83ec27529f67e0d477611fa6d8d6e6bd (diff) | |
| download | newlib-main.zip newlib-main.tar.gz newlib-main.tar.bz2 | |
Revert "Cygwin: spawn/exec: drop breaking away from job"HEADgithub/mastergithub/mainmastermain
This reverts commit c9933e57dab77816b5491c67917d4aac755fa4c6.
It turned out that the assumption from commit c9933e57dab7 ("Cygwin:
spawn/exec: drop breaking away from job") was blatantly incorrect.
Mintty is still triggering the Program Compatibility Assistant (PCA),
even on Windows 11, despite having a full, Windows 10/11-compatible
manifest. Apparently some heuristic in PCA finds something fishy
in mintty, but there's no way to avoid something for which there's
no explanation.
So we still need the PCA workaround.
Fixes: c9933e57dab7 ("Cygwin: spawn/exec: drop breaking away from job")
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
---
winsup/cygwin/dcrt0.cc | 2 +-
winsup/cygwin/fork.cc | 13 ++++++-
winsup/cygwin/globals.cc | 1 +
winsup/cygwin/local_includes/child_info.h | 2 +-
winsup/cygwin/resource.cc | 41 +++++++++++++++++++----
winsup/cygwin/spawn.cc | 11 ++++++
6 files changed, 60 insertions(+), 10 deletions(-)
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 1d5a452b4fbc..e080aa41bca2 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -894,7 +894,7 @@ dll_crt0_1 (void *)
uinfo_init (); /* initialize user info */
- setup_user_rlimits ();
+ enforce_breakaway_from_job = setup_user_rlimits (!child_proc_info);
if (child_proc_info)
child_proc_info->inherit_process_rlimits ();
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index eeed7155ee63..3e5d81fe46e8 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -152,7 +152,7 @@ frok::child (volatile char * volatile here)
clear_procimptoken ();
cygheap->user.reimpersonate ();
- setup_user_rlimits ();
+ setup_user_rlimits (false);
ch.inherit_process_rlimits ();
#ifdef DEBUGGING
@@ -253,6 +253,17 @@ frok::parent (volatile char * volatile stack_here)
systems. */
c_flags |= CREATE_UNICODE_ENVIRONMENT;
+ /* Despite all our executables having a valid manifest, "mintty" still
+ triggers the "Program Compatibility Assistant (PCA) Service" for
+ some reason, maybe due to some heuristics in PCA.
+ We use job objects for rlimits extensively, so we still have to let
+ child processes breakaway from job. Otherwise we can't add processes
+ running in different terminals to an already existing per-user job.
+ The check for this situation is now done in setup_user_rlimits()
+ called from dll_crt0_1(). */
+ if (enforce_breakaway_from_job)
+ c_flags |= CREATE_BREAKAWAY_FROM_JOB;
+
errmsg = NULL;
hchild = NULL;
diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc
index 86b0c2718a87..f73c35f88e7f 100644
--- a/winsup/cygwin/globals.cc
+++ b/winsup/cygwin/globals.cc
@@ -28,6 +28,7 @@ PWCHAR windows_directory = windows_directory_buf + 4;
UINT windows_directory_length;
UNICODE_STRING windows_directory_path;
WCHAR global_progname[NT_MAX_PATH];
+bool NO_COPY enforce_breakaway_from_job;
/* program exit the program */
diff --git a/winsup/cygwin/local_includes/child_info.h b/winsup/cygwin/local_includes/child_info.h
index f2e4fb165862..e10aa777610c 100644
--- a/winsup/cygwin/local_includes/child_info.h
+++ b/winsup/cygwin/local_includes/child_info.h
@@ -203,7 +203,7 @@ extern child_info_spawn ch_spawn;
#define have_execed_cygwin ch_spawn.has_execed_cygwin ()
/* resource.cc */
-extern void setup_user_rlimits ();
+extern bool setup_user_rlimits (bool);
extern "C" {
extern child_info *child_proc_info;
diff --git a/winsup/cygwin/resource.cc b/winsup/cygwin/resource.cc
index 83ae9add4cdb..12705eb36f78 100644
--- a/winsup/cygwin/resource.cc
+++ b/winsup/cygwin/resource.cc
@@ -376,8 +376,8 @@ child_info::inherit_process_rlimits ()
rlimit_as.rlim_max, rlimit_as.rlim_cur);
}
-static void
-__setup_user_rlimits_single (int flags)
+static bool
+__setup_user_rlimits_single (int flags, bool root_process)
{
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobinfo = { 0 };
NTSTATUS status = STATUS_SUCCESS;
@@ -385,6 +385,7 @@ __setup_user_rlimits_single (int flags)
UNICODE_STRING uname;
WCHAR jobname[32];
HANDLE job = NULL;
+ bool ret = false;
RtlInitUnicodeString (&uname, job_shared_name (jobname, PER_USER | flags));
InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF,
@@ -393,7 +394,7 @@ __setup_user_rlimits_single (int flags)
if (!NT_SUCCESS (status))
{
debug_printf ("NtCreateJobObject (%S): status %y", &uname, status);
- return;
+ return false;
}
/* Did we just create the job? */
if (status != STATUS_OBJECT_NAME_EXISTS)
@@ -404,6 +405,28 @@ __setup_user_rlimits_single (int flags)
&jobinfo, sizeof jobinfo);
}
NTSTATUS in_job = NtIsProcessInJob (NtCurrentProcess (), job);
+
+ /* Check if we're already running in a job, even though we're not
+ running in one of our own user-specific jobs. If so, this process
+ is doomed, but we can try to create child processes with
+ CREATE_BREAKAWAY_FROM_JOB, so at least the next process in the
+ process tree will be happy.
+ We're only checking processes which have been started from non-Cygwin
+ processes (root processes of a Cygwin process tree).
+ Given that breaking away also requires that the foreign job allows
+ JOB_OBJECT_LIMIT_BREAKAWAY_OK, we're testing this right here, too. */
+ if ((flags & HARD_LIMIT) && root_process
+ && in_job == STATUS_PROCESS_NOT_IN_JOB)
+ {
+ status = NtQueryInformationJobObject (NULL,
+ JobObjectExtendedLimitInformation,
+ &jobinfo, sizeof jobinfo, NULL);
+ if (NT_SUCCESS (status)
+ && (jobinfo.BasicLimitInformation.LimitFlags
+ & JOB_OBJECT_LIMIT_BREAKAWAY_OK))
+ ret = true;
+ }
+
/* Assign the process to the job if it's not already assigned. */
if (NT_SUCCESS (status) && in_job == STATUS_PROCESS_NOT_IN_JOB)
{
@@ -412,13 +435,17 @@ __setup_user_rlimits_single (int flags)
debug_printf ("NtAssignProcessToJobObject: %y\r", status);
}
/* Never close the handle. */
+ return ret;
}
-void
-setup_user_rlimits ()
+bool
+setup_user_rlimits (bool root_process)
{
- __setup_user_rlimits_single (HARD_LIMIT);
- __setup_user_rlimits_single (SOFT_LIMIT);
+ bool in_a_foreign_job;
+
+ in_a_foreign_job = __setup_user_rlimits_single (HARD_LIMIT, root_process);
+ __setup_user_rlimits_single (SOFT_LIMIT, false);
+ return in_a_foreign_job;
}
extern "C" int
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 44566c34790e..5b25f7c1cee1 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -407,6 +407,17 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
systems. */
c_flags |= CREATE_UNICODE_ENVIRONMENT;
+ /* Despite all our executables having a valid manifest, "mintty" still
+ triggers the "Program Compatibility Assistant (PCA) Service" for
+ some reason, maybe due to some heuristics in PCA.
+ We use job objects for rlimits extensively, so we still have to let
+ child processes breakaway from job. Otherwise we can't add processes
+ running in different terminals to an already existing per-user job.
+ The check for this situation is now done in setup_user_rlimits()
+ called from dll_crt0_1(). */
+ if (enforce_breakaway_from_job)
+ c_flags |= CREATE_BREAKAWAY_FROM_JOB;
+
/* 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
--
2.52.0
Diffstat (limited to 'newlib/libc/include/assert.h')
0 files changed, 0 insertions, 0 deletions
