Conversation
Otherwise if globbing is allowed and we get called from a Windows program, build_argv thinks we've been called from a Cygwin program.
…spec Reverts 25ba8f3. I can't figure out what the intention was. I'm sure I'll find out soon enough when everything breaks. This change means that input of: '"C:/test.exe SOME_VAR=\"literal quotes\""' becomes: 'C:/test.exe SOME_VAR="literal quotes"' instead of: 'C:/test.exe SOME_VAR=\literal quotes\' .. which is at least consistent with the result for: '"no_drive_or_colon SOME_VAR=\"literal quotes\""' The old result of course resulted in the quoted string being split into two arguments at the space which is clearly not intended. I *guess* backslashes in dos paths may have been the issue here? If so I don't care since we should not use them, ever, esp. not at the expense of sensible forward-slash-containing input.
Works very much like MSYS2_ARG_CONV_EXCL. In fact it uses the same function, arg_heuristic_with_exclusions (). Also refactors parsing the env. variables to use new function, string_split_delimited (). The env. that is searched through is the merged (POSIX + Windows) one. It remains to be seen if this should be made an option or not. This feature was prompted because the R language (Windows exe) calls bash to run configure.win, which then calls back into R to read its config variables (LOCAL_SOFT) and when this happens, msys2-runtime converts R_ARCH from "/x64" to an absolute Windows path and appends it to another absolute path, R_HOME, forming an invalid path.
It is simply the negation of `disable_pcon`, i.e. `MSYS=enable_pcon` is equivalent to `MSYS=nodisable_pcon` (the former is slightly more intuitive than the latter) and likewise `MSYS=noenable_pcon` is equivalent to `MSYS=disable_pcon` (here, the latter is definitely more intuitive than the former). This is needed because we just demoted the pseudo console feature to be opt-in instead of opt-out, and it would be awkward to recommend to users to use "nodisable_pcon"... "nodisable" is not even a verb. Signed-off-by: Johannes Schindelin <[email protected]>
We mount /usr/bin to /bin, but in a chroot this is broken and we have no /bin, so try to use the real path. chroot is used by pacman to run install scripts when called with --root and this broke programs in install scripts calling popen() (install-info from texinfo for example) There are more paths hardcoded to /bin in cygwin which might also be broken in this scenario, so this maybe should be extended to all of them.
It does not work at all. For example, `rpm -E %fedora` says that there should be version 33 of rpmsphere at https://github.com/rpmsphere/noarch/tree/master/r, but there is only version 32. Another thing that is broken: Cygwin now assumes that a recent mingw-w64-headers version is available, but Fedora apparently only offers v7.0.0, which is definitely too old to accommodate for the expectation of cygwin/cygwin@c1f7c4d1b6d7. Signed-off-by: Johannes Schindelin <[email protected]>
Build with --disable-dependency-tracking because we only build once and this saves 3-4 minutes in CI.
This will help us by automating an otherwise tedious task. Signed-off-by: Johannes Schindelin <[email protected]>
In the Cygwin project, it was decided that the command-line of Cygwin processes, as shown in the output of `wmic process list`, would suffer from being truncated to 32k (and is transmitted to the child process via a different mechanism, anyway), and therefore only the absolute path of the executable is shown by default. Users who would like to see the full command-line (even if it is truncated) are expected to set `CYGWIN=wincmdln` (or, in MSYS2's case, `MSYS=wincmdln`). Seeing as MSYS2 tries to integrate much better with the surrounding Win32 ecosystem than Cygwin, it makes sense to turn this on by default. Users who wish to suppress it can still set `MSYS=nowincmdln`. Signed-off-by: Johannes Schindelin <[email protected]>
In particular, we are interested in the address of the CtrlRoutine and the ExitProcess functions. Since kernel32.dll is loaded first thing, the addresses will be the same for all processes (matching the CPU architecture, of course). This will help us with emulating SIGINT properly (by not sending signals to *all* processes attached to the same Console, as GenerateConsoleCtrlEvent() would do). Co-authored-by: Naveen M K <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]>
This patch is heavily inspired by the Git for Windows' strategy in handling Ctrl+C. When a process is terminated via TerminateProcess(), it has no chance to do anything in the way of cleaning up. This is particularly noticeable when a lengthy Git for Windows process tries to update Git's index file and leaves behind an index.lock file. Git's idea is to remove the stale index.lock file in that case, using the signal and atexit handlers available in Linux. But those signal handlers never run. Note: this is not an issue for MSYS2 processes because MSYS2 emulates Unix' signal system accurately, both for the process sending the kill signal and the process receiving it. Win32 processes do not have such a signal handler, though, instead MSYS2 shuts them down via `TerminateProcess()`. For a while, Git for Windows tried to use a gentler method, described in the Dr Dobb's article "A Safer Alternative to TerminateProcess()" by Andrew Tucker (July 1, 1999), http://www.drdobbs.com/a-safer-alternative-to-terminateprocess/184416547 Essentially, we injected a new thread into the running process that does nothing else than running the ExitProcess() function. However, this was still not in line with the way CMD handles Ctrl+C: it gives processes a chance to do something upon Ctrl+C by calling SetConsoleCtrlHandler(), and ExitProcess() simply never calls that handler. So for a while we tried to handle SIGINT/SIGTERM by attaching to the console of the command to interrupt, and generating the very same event as CMD does via GenerateConsoleCtrlEvent(). This method *still* was not correct, though, as it would interrupt *every* process attached to that Console, not just the process (and its children) that we wanted to signal. A symptom was that hitting Ctrl+C while `git log` was shown in the pager would interrupt *the pager*. The method we settled on is to emulate what GenerateConsoleCtrlEvent() does, but on a process by process basis: inject a remote thread and call the (private) function kernel32!CtrlRoutine. To obtain said function's address, we use the dbghelp API to generate a stack trace from a handler configured via SetConsoleCtrlHandler() and triggered via GenerateConsoleCtrlEvent(). To avoid killing each and all processes attached to the same Console as the MSYS2 runtime, we modify the cygwin-console-helper to optionally print the address of kernel32!CtrlRoutine to stdout, and then spawn it with a new Console. Note that this also opens the door to handling 32-bit process from a 64-bit MSYS2 runtime and vice versa, by letting the MSYS2 runtime look for the cygwin-console-helper.exe of the "other architecture" in a specific place (we choose /usr/libexec/, as it seems to be the convention for helper .exe files that are not intended for public consumption). The 32-bit helper implicitly links to libgcc_s_dw2.dll and libwinpthread-1.dll, so to avoid cluttering /usr/libexec/, we look for the helped of the "other" architecture in the corresponding mingw32/ or mingw64/ subdirectory. Among other bugs, this strategy to handle Ctrl+C fixes the MSYS2 side of the bug where interrupting `git clone https://...` would send the spawned-off `git remote-https` process into the background instead of interrupting it, i.e. the clone would continue and its progress would be reported mercilessly to the console window without the user being able to do anything about it (short of firing up the task manager and killing the appropriate task manually). Note that this special-handling is only necessary when *MSYS2* handles the Ctrl+C event, e.g. when interrupting a process started from within MinTTY or any other non-cmd-based terminal emulator. If the process was started from within `cmd.exe`'s terminal window, child processes are already killed appropriately upon Ctrl+C, by `cmd.exe` itself. Also, we can't trust the processes to end it's subprocesses upon receiving Ctrl+C. For example, `pip.exe` from `python-pip` doesn't kill the python it lauches (it tries to but fails), and I noticed that in cmd it kills python also correctly, which mean we should kill all the process using `exit_process_tree`. Co-authored-by: Naveen M K <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]>
This change is the equivalent to the change to the Ctrl+C handling we just made. Co-authored-by: Naveen M K <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]>
This code has been causing issues with SUBST and mapped network drives, so add an option (defaulted to on) which can be used to disable it where needed. MSYS=nonativeinnerlinks
The MSYS2 packages lack the infrastructure to build those. Signed-off-by: Johannes Schindelin <[email protected]>
Before symlinking libg.a, we need the symlink source `libmsys-2.0.a`: in MSYS2, we copy by default (if we were creating Unix-style symlinks, the target would not have to exist before symlinking, but when copying we do need the source _right away_). Signed-off-by: Johannes Schindelin <[email protected]>
When calling a non-MSys2 binary, all of the environment is converted from POSIX to Win32, including the SHELL environment variable. In Git for Windows, for example, `SHELL=/usr/bin/bash` is converted to `SHELL=C:\Program Files\Git\usr\bin\bash.exe` when calling the `git.exe` binary. This is appropriate because non-MSys2 binaries would not handle POSIX paths correctly. Under certain circumstances, however, `git.exe` calls an *MSys2* binary in turn, such as `git config --edit` calling `vim.exe` unless Git is configured to use another editor specifically. Now, when this "improved vi" calls shell commands, it uses that $SHELL variable *without quoting*, resulting in a nasty error: C:\Program: No such file or directory Many other programs behave in the same manner, assuming that $SHELL does not contain spaces and hence needs no quoting, unfortunately including some of Git's own scripts. Therefore let's make sure that $SHELL gets "posified" again when entering MSys2 programs. Earlier attempts by Git for Windows contributors claimed that adding `SHELL` to the `conv_envvars` array does not have the intended effect. These reports just missed that the `conv_start_chars` array (which makes the code more performant) needs to be adjusted, too. Note that we set the `immediate` flag to `true` so that the environment variable is set immediately by the MSys2 runtime, i.e. not only spawned processes will see the POSIX-ified `SHELL` variable, but the MSys2 runtime *itself*, too. This fixes git-for-windows/git#542, git-for-windows/git#498, and git-for-windows/git#468. Signed-off-by: Johannes Schindelin <[email protected]>
MSYS2 recently introduced that hack where the ORIGINAL_PATH variable is set to the original PATH value in /etc/profile, unless previously set. In Git for Windows' default mode, that ORIGINAL_PATH value is the used to define the PATH variable explicitly. So far so good. The problem: when calling from inside an MSYS2 process (such as Bash) a MINGW executable (such as git.exe) that then calls another MSYS2 executable (such as bash.exe), that latter call will try to re-convert ORIGINAL_PATH after the previous call converted ORIGINAL_PATH from POSIX to Windows paths. And this conversion may very well fail, e.g. when the path list contains mixed semicolons and colons. So let's just *force* the MSYS2 runtime to handle ORIGINAL_PATH in the same way as the PATH variable (which conversion works, as we know). Signed-off-by: Johannes Schindelin <[email protected]>
We are currently trying to move our cygwin build environment closer to cygwin and some autotools/bash based build systems call "uname -s" to figure out the OS and in many cases only handle the cygwin case, so we have to patch them. With this instead of patching we can set MSYSTEM=CYGWIN and change uname output that way. The next step would be to always output CYGWIN in an msys env by default, but for now this allows us to get rid of all the patches without affecting users.
There is a difference between an empty value and an unset environment variable. We should not confuse both; If the user wants to unset an environment variable, they can certainly do so (unsetenv(3), or in the shell: 'unset ABC'). This fixes Git's t3301-notes.sh, which overrides environment variables with empty values. Signed-off-by: Johannes Schindelin <[email protected]>
We just disabled the code that skips environment variables whose values are empty. However, this code was introduced a long time ago into Cygwin in d6b1ac7 (* environ.cc (build_env): Don't put an empty environment variable into the environment. Optimize use of "len". * errno.cc (ERROR_MORE_DATA): Translate to EMSGSIZE rather than EAGAIN., 2006-09-07), seemingly without any complaints. Meaning: There might very well be use cases out there where it makes sense to skip empty-valued environment variables. Therefore, it seems like a good idea to have a "knob" to turn it back on. With this commit, we introduce such a knob: by setting `noemptyenvvalues` the `MSYS` variable (or appending it if that variable is already set), users can tell the MSYS2 runtime to behave just like in the olden times. Signed-off-by: Johannes Schindelin <[email protected]>
With this commit, you can call MSYS=noemptyenvvalues my-command and it does what is expected: to pass no empty-valued environment variables to `my-command`. Signed-off-by: Johannes Schindelin <[email protected]>
This reverts commit 943433b. This seems to fix fork errors under Docker, see https://cygwin.com/pipermail/cygwin/2022-December/252711.html
It frequently leads to problems when trying, say, to call from MSYS2's
Bash into Cygwin's or Git for Windows', merely because sharing that data
is pretty finicky.
For example, using the MSYS2' Bash using the MSYS2 runtime version that
is current at time of writing, trying to call Cygwin's programs fails
in manners like this:
$ /c/cygwin64/bin/uname -r
0 [main] uname (9540) child_copy: cygheap read copy failed, 0x800000000..0x800010BE0, done 0, windows pid 9540, Win32 error 6
680 [main] uname 880 C:\cygwin64\bin\uname.exe: *** fatal error - couldn't create signal pipe, Win32 error 5
with the rather misleading exit code 127 (a code which is reserved to
indicate that a command was not found).
Let's just treat the MSYS2 runtime and the Cygwin runtime as completely
incompatible with one another, by virtue of using a different
magic constant than merely `CHILD_INFO_MAGIC`.
By using the msys2-runtime commit to modify that magic constant, we can
even spawn programs using a different MSYS2 runtime (such as Git for
Windows') because the commit serves as the tell-tale whether two MSYS2
runtime versions are compatible with each other. To support building in
the MSYS2-packages repository (where we do not check out the
`msys2-runtime` but instead check out Cygwin and apply patches on top),
let's accept a hard-coded commit hash as `./configure` option.
One consequence is that spawned MSYS processes using a different MSYS2
runtime will not be visible as such to the parent process, i.e. they
cannot share any resources such as pseudo terminals. But that's okay,
they are simply treated as if they were regular Win32 programs.
Note: We have to use a very rare form of encoding the brackets in the
`expr` calls: quadrigraphs (for a thorough explanation, see
https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.70/html_node/Quadrigraphs.html#Quadrigraphs).
This is necessary because it is apparently impossible to encode brackets
in `configure.ac` files otherwise.
Signed-off-by: Johannes Schindelin <[email protected]>
Having just Cygwin's version in the output of `uname` is not helpful, as both MSYS2 as well as Git for Windows release intermediate versions of the MSYS2 runtime much more often than Cygwin runtime versions are released. Signed-off-by: Johannes Schindelin <[email protected]>
Reportedly a very recent internal build of Windows 11 once again changed the current working directory logic a bit, and Cygwin's "magic" (or: "technologically sufficiently advanced") code needs to be adjusted accordingly. In particular, the following assembly code can be seen: ntdll!RtlpReferenceCurrentDirectory 598 00000001`800c6925 488d0db4cd0f00 lea rcx,[ntdll!FastPebLock (00000001`801c36e0)] 583 00000001`800c692c 4c897810 mov qword ptr [rax+10h],r15 588 00000001`800c6930 0f1140c8 movups xmmword ptr [rax-38h],xmm0 598 00000001`800c6934 e82774f4ff call ntdll!RtlEnterCriticalSection The change necessarily looks a bit different than 4840a56 (Cygwin: Adjust CWD magic to accommodate for the latest Windows previews, 2023-05-22): The needle `\x48\x8d\x0d` is already present, as the first version of the hack after Windows 8.1 was released. In that code, though, the `call` to `RtlEnterCriticalSection` followed the `lea` instruction immediately, but now there are two more instructions separating them. Note: In the long run, we may very well want to follow the insightful suggestion by a helpful Windows kernel engineer who pointed out that it may be less fragile to implement kind of a disassembler that has a better chance to adapt to the ever-changing code of `ntdll!RtlpReferenceCurrentDirectory` by skipping uninteresting instructions such as `mov %rsp,%rax`, `mov %rbx,0x20(%rax)`, `push %rsi` `sub $0x70,%rsp`, etc, and focuses on finding the `lea`, `call ntdll!RtlEnterCriticalSection` and `mov ..., rbx` instructions, much like it was prototyped out for ARM64 at https://gist.github.com/jeremyd2019/aa167df0a0ae422fa6ebaea5b60c80c9 Signed-off-by: Johannes Schindelin <[email protected]>
This commit starts the rebase of e997f85 to 98a63f7b94
Seeing as Git for Windows tries to stay close to the upstream MSYS2 project, it makes sense to integrate their patches verbatim. Signed-off-by: Johannes Schindelin <[email protected]>
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@v2...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <[email protected]>
See https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot#enabling-dependabot-version-updates-for-actions for details. Signed-off-by: Johannes Schindelin <[email protected]>
…unction This code is way too useful _not_ to make it reusable. While at it, improve on the timeout logic to be quite a bit more precise. Signed-off-by: Johannes Schindelin <[email protected]>
It used only 3 spaces, when 4 were called for. Signed-off-by: Johannes Schindelin <[email protected]>
There is actually no need to have a flashing window just to capture the output of the command: using the trick (use `Run()`, pipe to `clip` and then use `A_Clipboard`) from https://stackoverflow.com/a/32298415 makes it possible to hide the console window _and_ capture the output. Signed-off-by: Johannes Schindelin <[email protected]>
The `uname` executable is not on the `PATH` by default. Let's use the Git alias trick to execute it, then. Signed-off-by: Johannes Schindelin <[email protected]>
When the command fails, we should not simply continue, mistaking an empty string for being the valid output of a successful run. Signed-off-by: Johannes Schindelin <[email protected]>
The Ctrl+C way to interrupt run-away processes is highly important. It was recently broken in multiple ways in the Cygwin runtime (and hence also in the MSYS2 runtime). Let's add some integration tests that will catch regressions. It is admittedly less than ideal to add _integration_ tests; While imitating exactly what the end user does looks appealing at first, excellent tests impress by how quickly they allow regressions not only to be identified but also to be fixed. Even worse: all integration tests, by virtue of working in a broader environment than, say, unit tests, incur the price of sometimes catching unactionable bugs, i.e. bugs in software that is both outside of our control as well as not the target of our testing at all. Nevertheless, seeing as Cygwin did not add any unit tests for those Ctrl+C fixes (which is understandable, given how complex testing for Ctrl+C without UI testing would be), it is better to have integration tests than no tests at all. So here goes: This commit introduces a test that verifies that the MSYS2 `sleep.exe` can be interrupted when run from PowerShell in a Windows Terminal. This was broken in v3.6.0 and fixed in 7674c51 (Cygwin: console: Set ENABLE_PROCESSED_INPUT when disable_master_thread, 2025-07-01). Signed-off-by: Johannes Schindelin <[email protected]>
This imitates Unix shell's `$(...)` behavior better and is eminently more useful when capturing, say, the output of `cygpath`. Signed-off-by: Johannes Schindelin <[email protected]>
I want to add an integration test that clones a repository via SSH. Unfortunately, I have not found a better way than to run OpenSSH for Windows' `sshd.exe` in debug mode, in which case every successful connection will open a terminal window. Let's be prepared for these annoying extra windows by forcefully activating the desired window as needed. This change is admittedly a bit intrusive; I did not find any more elegant way to achieve the same result, though. Signed-off-by: Johannes Schindelin <[email protected]>
This was the actual use case that was broken and necessitated the fix in 7674c51 (Cygwin: console: Set ENABLE_PROCESSED_INPUT when disable_master_thread, 2025-07-01). It does require an SSH server, which Git for Windows no longer ships. Therefore, this test uses the `sshd.exe` of OpenSSH for Windows (https://github.com/powershell/Win32-OpenSSH) in conjunction with Git for Windows' `ssh.exe` (because using OpenSSH for Windows' variant of `ssh.exe` would not exercise the MSYS2 runtime and therefore not demonstrate a regression, should it surface in the future). To avoid failing the test because OpenSSH for Windows is not available, the test case is guarded by the environment variable `OPENSSH_FOR_WINDOWS_DIRECTORY` which needs to point to a directory that contains a working `sshd.exe`. Signed-off-by: Johannes Schindelin <[email protected]>
In the previous commit, I added a new UI test that generates a somewhat large repository for testing the clone via SSH. Since that repository is created in the test directory, that would inflate the `ui-tests` build artifact rather dramatically. So let's create the repository outside of that directory. Signed-off-by: Johannes Schindelin <[email protected]>
…thread
With the commit 476135a24506, set_input_mode() reffers to the flag
disable_master_thread in tty::cygwin mode. So it is necessary to call
set_input_mode() after changing disable_master_thread flag. However,
the commit 476135a24506 was missing that.
With this patch, set_input_mode() is called after changing the flag
disable_master_thread, if the console input mode is tty::cygwin.
Fixes: 476135a24506 ("Cygwin: console: Set ENABLE_PROCESSED_INPUT when disable_master_thread");
Signed-off-by: Takashi Yano <[email protected]>
Cherry-picked-from: 65a48c7202 (Cygwin: console: Call set_input_mode() after changing disable_master_thread, 2025-07-03)
Signed-off-by: Johannes Schindelin <[email protected]>
The fixes of 7674c51 (Cygwin: console: Set ENABLE_PROCESSED_INPUT when disable_master_thread, 2025-07-01) were unfortunately not complete; There were still a couple of edge cases where Ctrl+C was unable to interrupt processes. Let's add a demonstration of that issue. Signed-off-by: Johannes Schindelin <[email protected]>
In 0ae6a6f (Cygwin: pipe: Fix SSH hang with non-cygwin pipe reader, 2025-06-27), a quite problematic bug was fixed where somewhat large-ish repositories could not be cloned via SSH anymore. This fix was not accompanied by a corresponding test case in Cygwin's test suite, i.e. there is no automated way to ensure that there won't be any regressions on that bug (and therefore it would fall onto end users to deal with those). This constitutes what Michael C. Feathers famously characterized as "legacy code" in his book "Working Effectively with Legacy Code": To me, legacy code is simply code without tests. I've gotten some grief for this definition. What do tests have to do with whether code is bad? To me, the answer is straightforward, and it is a point that I elaborate throughout the book: Code without tests is bad code. It doesn’t matter how well written it is; it doesn’t matter how pretty or object-oriented or well-encapsulated it is. With tests, we can change the behavior of our code quickly and verifiably. Without them, we really don’t know if our code is getting better or worse. Just to drive this point home, let me pull out Exhibit A: The bug fix in question, which is the latest (and hopefully last) commit in a _long_ chain of bug fixes that fix bugs introduced by preceding bug fixes: - 9e4d308 (Cygwin: pipe: Adopt FILE_SYNCHRONOUS_IO_NONALERT flag for read pipe., 2021-11-10) fixed a bug where Cygwin hung by mistake while piping output from one .NET program as input to another .NET program (potentially introduced by 3651990 (Cygwin: pipe: Avoid false EOF while reading output of C# programs., 2021-11-07), which was itself a bug fix). It introduced a bug that was fixed by... - fc691d0 (Cygwin: pipe: Make sure to set read pipe non-blocking for cygwin apps., 2024-03-11). Which introduced a bug that was purportedly fixed by... - 7ed9adb (Cygwin: pipe: Switch pipe mode to blocking mode by default, 2024-09-05). Which introduced a bug that was fixed by... - cbfaeba (Cygwin: pipe: Fix incorrect write length in raw_write(), 2024-11-06). Which introduced a bug that was fixed by... the SSH hang fix in 0ae6a6f (Cygwin: pipe: Fix SSH hang with non-cygwin pipe reader, 2025-06-27). There is not only the common thread here that each of these bug fixes introduced a new bug, but also the common thread that none of the commits introduced new test cases into the test suite that could potentially have helped prevent future breakages in this code. So let's at least add an integration test here. Side note: I am quite unhappy with introducing integration tests. I know there are a lot of fans out there, but I cannot help wondering whether they favor the convenience of writing tests quickly over the vast cost of making debugging any regression a highly cumbersome and unenjoyable affair (try single-stepping through a test case that requires several processes to be orchestrated in unison). Also, integration tests have the large price of introducing moving parts outside the code base that is actually to be tested, opening the door for breakages caused by software (or infrastructure, think: network glitches!) that are completely outside the power or responsibility of the poor engineer tasked with fixing the breakages. Nevertheless, I have been unable despite days of trying to wrap my head around the issue to figure out a way to reproduce the `fhandler_pipe_fifo::raw_write()` hang without involving a MINGW `git.exe` and an MSYS2/Cygwin `ssh.exe`. So: It's the best I could do with any reasonable amount of effort. It's better to have integration tests that would demonstrate regressions than not having any tests for that at all. Signed-off-by: Johannes Schindelin <[email protected]>
... excluding the 1.23 release train that is currently marked as pre-release. Signed-off-by: Johannes Schindelin <[email protected]>
dscho
added a commit
that referenced
this pull request
Jun 26, 2026
The Ctrl+C UI test launches OpenSSH for Windows' `sshd.exe` via `Run` and then immediately types the `git clone` keystrokes into the PowerShell window. On the current windows-2025 runners, sshd's cold-start can take long enough that by the time `ssh` attempts the TCP connect, the listening socket isn't bound yet; the clone never produces `remote:`, the `WaitForRegExInWindowsTerminal` for it times out, and the test fails. This was the failure on attempt #1 of the latest CI run on `fix-pcon-grandchild-cons0`. Probe sshd with `ssh ... echo hi` via `RunWait` before letting the clone proceed, sleeping 5 seconds between attempts and giving up after a minute. The probe runs directly, not through the Windows Terminal, so it does not perturb the WT buffer the test is observing. Run the same probe again before the verification clones, since the test `Run`s sshd a second time there and could race that cold-start too. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <[email protected]>
dscho
added a commit
that referenced
this pull request
Jun 26, 2026
The Ctrl+C UI test starts up an OpenSSH-for-Windows `sshd.exe` to exercise the SSH-based clone scenarios, and intentionally leaves it running once the test script exits: it has no `Run` wrapper that would tear it down, and the test does not own a clean shutdown path for it. When `actions/upload-artifact` then tries to zip up the `ui-tests` directory, it fails with `EPERM` on `ui-tests/ctrl-c/ssh_host_rsa_key`, because `sshd.exe` still holds an exclusive handle on the host key file, and the entire upload step aborts. That is the failure observed on attempt #1 of the latest CI run on `fix-pcon-grandchild-cons0`. Stop any leftover `sshd.exe` instances before uploading. The runner is ephemeral and dedicated to the job, so identifying the process by name is safe; the actual termination still goes through `Stop-Process -Id` to keep the kill targeted. `if: always()` mirrors the upload step so the cleanup runs whether the test passed or failed. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <[email protected]>
dscho
added a commit
that referenced
this pull request
Jun 26, 2026
The Ctrl+C UI test launches OpenSSH for Windows' `sshd.exe` via `Run` and then immediately types the `git clone` keystrokes into the PowerShell window. On the current windows-2025 runners, sshd's cold-start can take long enough that by the time `ssh` attempts the TCP connect the listening socket isn't bound yet; the clone never produces `remote:`, the `WaitForRegExInWindowsTerminal` for it times out, and the test fails. This was the failure on attempt #1 of the latest CI run on `fix-pcon-grandchild-cons0`. A naive fix that probes sshd with `ssh ... echo hi` has a fatal flaw given the test's `sshdOptions`: `sshd -d` (which the test relies on for verbose debug logs) only handles a single connection before exiting, so the probe itself consumes the slot the actual clone needed and the clone then gets `Connection refused`. That was the failure on runs/28233821130. Wait by polling `sshd.log` for the `Server listening on` message instead; the probe stays out-of-band, leaves sshd's one connection slot intact for the clone, and is essentially free (500 ms poll, 60 s deadline). A `static` counter tracks how many `Server listening on` lines have been acknowledged so far, so any future call site (e.g. after the verification re-start) would correctly wait for a fresh message past the previously seen ones rather than matching a stale entry. `Server listening on` is logged at `VERBOSE` and above; spell out `LogLevel VERBOSE` in `sshd_config` so the new wait does not silently depend on the command-line `-d` flags continuing to imply that verbosity. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <[email protected]>
dscho
added a commit
that referenced
this pull request
Jun 26, 2026
The Ctrl+C UI test starts up an OpenSSH-for-Windows `sshd.exe` to exercise the SSH-based clone scenarios, and intentionally leaves it running once the test script exits: it has no `Run` wrapper that would tear it down, and the test does not own a clean shutdown path for it. When `actions/upload-artifact` then tries to zip up the `ui-tests` directory, it fails with `EPERM` on `ui-tests/ctrl-c/ssh_host_rsa_key`, because `sshd.exe` still holds an exclusive handle on the host key file, and the entire upload step aborts. That is the failure observed on attempt #1 of the latest CI run on `fix-pcon-grandchild-cons0`. Stop any leftover `sshd.exe` instances before uploading. The runner is ephemeral and dedicated to the job, so identifying the process by name is safe; the actual termination still goes through `Stop-Process -Id` to keep the kill targeted. `if: always()` mirrors the upload step so the cleanup runs whether the test passed or failed. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <[email protected]>
dscho
added a commit
that referenced
this pull request
Jun 26, 2026
The Ctrl+C UI test launches OpenSSH for Windows' `sshd.exe` via `Run` and then immediately types the `git clone` keystrokes into the PowerShell window. On the current windows-2025 runners, sshd's cold-start can take long enough that by the time `ssh` attempts the TCP connect the listening socket isn't bound yet; the clone never produces `remote:`, the `WaitForRegExInWindowsTerminal` for it times out, and the test fails. This was the failure on attempt #1 of the first CI run on `fix-pcon-grandchild-cons0`. A naive fix that probes sshd with `ssh ... echo hi` has a fatal flaw given the test's `sshdOptions`: `sshd -d` (which the test relies on for verbose debug logs) only handles a single connection before exiting, so the probe itself consumes the slot the actual clone needed and the clone then gets `Connection refused`. That was the failure on runs/28233821130. Wait by polling `sshd.log` for the `Server listening on` message instead; the probe stays out-of-band, leaves sshd's one connection slot intact for the clone, and is essentially free (500 ms poll, 60 s deadline). A `static` counter tracks how many `Server listening on` lines have been acknowledged so far, so any future call site (e.g. after the verification re-start) would correctly wait for a fresh message past the previously seen ones rather than matching a stale entry. Spell out the logging configuration this poll depends on, in two places. First, pass an absolute path to `-E`: the relative `-E sshd.log` that was there before silently produced no log file at all when reproduced locally with OpenSSH for Windows 9.8.3.0p2 (the version the workflow installs); sshd reports no error on its own stderr/stdout and the file is never created anywhere reachable, so `WaitForSshd` would time out at 60 seconds. This was the failure on runs/28243902161. Second, set `LogLevel VERBOSE` in `sshd_config`: `Server listening on` is logged at `VERBOSE` and above, and spelling it out keeps the new wait from silently depending on the command-line `-d` flags continuing to imply that verbosity. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <[email protected]>
dscho
added a commit
that referenced
this pull request
Jun 26, 2026
The Ctrl+C UI test starts up an OpenSSH-for-Windows `sshd.exe` to exercise the SSH-based clone scenarios, and intentionally leaves it running once the test script exits: it has no `Run` wrapper that would tear it down, and the test does not own a clean shutdown path for it. When `actions/upload-artifact` then tries to zip up the `ui-tests` directory, it fails with `EPERM` on `ui-tests/ctrl-c/ssh_host_rsa_key`, because `sshd.exe` still holds an exclusive handle on the host key file, and the entire upload step aborts. That is the failure observed on attempt #1 of the latest CI run on `fix-pcon-grandchild-cons0`. Stop any leftover `sshd.exe` instances before uploading. The runner is ephemeral and dedicated to the job, so identifying the process by name is safe; the actual termination still goes through `Stop-Process -Id` to keep the kill targeted. `if: always()` mirrors the upload step so the cleanup runs whether the test passed or failed. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <[email protected]>
dscho
added a commit
that referenced
this pull request
Jun 26, 2026
The Ctrl+C UI test launches OpenSSH for Windows' `sshd.exe` via `Run` and then immediately types the `git clone` keystrokes into the PowerShell window. On the current windows-2025 runners, sshd's cold-start can take long enough that by the time `ssh` attempts the TCP connect the listening socket isn't bound yet; the clone never produces `remote:`, the `WaitForRegExInWindowsTerminal` for it times out, and the test fails. This was the failure on attempt #1 of the first CI run on `fix-pcon-grandchild-cons0`. Use sshd's own readiness signal. Per OpenSSH's `sshd.c`, the `PidFile` is `fopen`/`fprintf`/`fclose`'d immediately before the accept loop, after the listen sockets are bound and the sigterm handler is installed; its existence is a definitive "ready to accept" signal. The file is closed after the write, so there is no buffering window and no exclusive lock for a poller to fight. Configure `PidFile` in `sshd_config`, drop `-d -d -d` (sshd explicitly suppresses `PidFile` writes in `debug_flag` mode, see `if (options.pid_file != NULL && !debug_flag)` in `sshd.c`), and poll `sshd.pid` for both existence and non-empty content from `WaitForSshd`. Dropping `-d` has the deliberate side effect of making sshd multi-connection again. The previous attempts at fixing the flake had to fight that constraint at every turn: an `ssh ... echo hi` probe was abandoned because it consumed sshd's only allowed connection before the actual clone could run (runs/28233821130); a follow-up "poll sshd.log for `Server listening on`" probe was abandoned because sshd's `-E` log file is opened without share-read, so neither AHK's `FileRead`, PowerShell's `Get-Content`, nor MSYS2's `grep.exe` can open it while sshd is alive (runs/28243902161 — verified locally with OpenSSH for Windows 9.8.3.0p2). Multi-connection sshd lets the verification-clone path also stop being a single-shot dance, but the existing `Run` plus `restart sshd inside the retry loop` code is left as-is here; it is now a harmless no-op rather than load-bearing. The `-E sshd.log` argument is kept (with the same absolute `workTree`-anchored path as before) so the debug log is still captured by `Upload test results` for post-mortem analysis; the new probe does not depend on its contents. `LogLevel VERBOSE` in `sshd_config` is kept too, both because `Server listening on` is useful at that level and because making the logging configuration explicit shouldn't depend on which command-line flags happen to be set. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <[email protected]>
dscho
added a commit
that referenced
this pull request
Jun 26, 2026
The Ctrl+C UI test starts up an OpenSSH-for-Windows `sshd.exe` to exercise the SSH-based clone scenarios, and intentionally leaves it running once the test script exits: it has no `Run` wrapper that would tear it down, and the test does not own a clean shutdown path for it. When `actions/upload-artifact` then tries to zip up the `ui-tests` directory, it fails with `EPERM` on `ui-tests/ctrl-c/ssh_host_rsa_key`, because `sshd.exe` still holds an exclusive handle on the host key file, and the entire upload step aborts. That is the failure observed on attempt #1 of the latest CI run on `fix-pcon-grandchild-cons0`. Stop any leftover `sshd.exe` instances before uploading. The runner is ephemeral and dedicated to the job, so identifying the process by name is safe; the actual termination still goes through `Stop-Process -Id` to keep the kill targeted. `if: always()` mirrors the upload step so the cleanup runs whether the test passed or failed. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <[email protected]>
dscho
added a commit
that referenced
this pull request
Jun 26, 2026
The Ctrl+C UI test launches OpenSSH for Windows' `sshd.exe` via `Run` and then immediately types the `git clone` keystrokes into the PowerShell window. On the current windows-2025 runners, sshd's cold-start can take long enough that by the time `ssh` attempts the TCP connect the listening socket isn't bound yet; the clone never produces `remote:`, the `WaitForRegExInWindowsTerminal` for it times out, and the test fails. This was the failure on attempt #1 of the first CI run on `fix-pcon-grandchild-cons0`. Use sshd's own readiness signal. Per OpenSSH's `sshd.c`, the `PidFile` is `fopen`/`fprintf`/`fclose`'d immediately before the accept loop, after the listen sockets are bound and the sigterm handler is installed; its existence is a definitive "ready to accept" signal. The file is closed after the write, so there is no buffering window and no exclusive lock for a poller to fight. Configure `PidFile` in `sshd_config`, drop `-d -d -d` (sshd explicitly suppresses `PidFile` writes in `debug_flag` mode, see `if (options.pid_file != NULL && !debug_flag)` in `sshd.c`), and poll `sshd.pid` for both existence and non-empty content from `WaitForSshd`. Dropping `-d` has the deliberate side effect of making sshd multi-connection again. The previous attempts at fixing the flake had to fight that constraint at every turn: an `ssh ... echo hi` probe was abandoned because it consumed sshd's only allowed connection before the actual clone could run (runs/28233821130); a follow-up "poll sshd.log for `Server listening on`" probe was abandoned because sshd's `-E` log file is opened without share-read, so neither AHK's `FileRead`, PowerShell's `Get-Content`, nor MSYS2's `grep.exe` can open it while sshd is alive (runs/28243902161, verified locally with OpenSSH for Windows 9.8.3.0p2). Multi-connection sshd lets the verification-clone path also stop being a single-shot dance, but the existing `Run` plus `restart sshd inside the retry loop` code is left as-is here; it is now a harmless no-op rather than load-bearing. The flip side of long-lived sshd is that it now outlives the test script's body, and the next thing the script does is `CleanUpWorkTree` which `DirDelete`s the worktree out from under sshd's still-open `sshd.pid` and `sshd.log` handles. That hangs on Windows (runs/28256992298, observed locally). Stop sshd via the PID we just learned to read before exiting the `if` block, so the worktree is releasable by the time `CleanUpWorkTree` runs. The `-E sshd.log` argument is kept (with the same absolute `workTree`-anchored path as before) so the debug log is still captured by `Upload test results` for post-mortem analysis; the new probe does not depend on its contents. `LogLevel VERBOSE` in `sshd_config` is kept too, both because `Server listening on` is useful at that level and because making the logging configuration explicit shouldn't depend on which command-line flags happen to be set. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <[email protected]>
dscho
added a commit
that referenced
this pull request
Jun 26, 2026
The Ctrl+C UI test starts up an OpenSSH-for-Windows `sshd.exe` to exercise the SSH-based clone scenarios, and intentionally leaves it running once the test script exits: it has no `Run` wrapper that would tear it down, and the test does not own a clean shutdown path for it. When `actions/upload-artifact` then tries to zip up the `ui-tests` directory, it fails with `EPERM` on `ui-tests/ctrl-c/ssh_host_rsa_key`, because `sshd.exe` still holds an exclusive handle on the host key file, and the entire upload step aborts. That is the failure observed on attempt #1 of the latest CI run on `fix-pcon-grandchild-cons0`. Stop any leftover `sshd.exe` instances before uploading. The runner is ephemeral and dedicated to the job, so identifying the process by name is safe; the actual termination still goes through `Stop-Process -Id` to keep the kill targeted. `if: always()` mirrors the upload step so the cleanup runs whether the test passed or failed. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <[email protected]>
dscho
added a commit
that referenced
this pull request
Jun 26, 2026
The Ctrl+C UI test launches OpenSSH for Windows' `sshd.exe` via `Run` and then immediately types the `git clone` keystrokes into the PowerShell window. On the current windows-2025 runners, sshd's cold-start can take long enough that by the time `ssh` attempts the TCP connect the listening socket isn't bound yet; the clone never produces `remote:`, the `WaitForRegExInWindowsTerminal` for it times out, and the test fails. This was the failure on attempt #1 of the first CI run on `fix-pcon-grandchild-cons0`. Use sshd's own readiness signal. Per OpenSSH's `sshd.c`, the `PidFile` is `fopen`/`fprintf`/`fclose`'d immediately before the accept loop, after the listen sockets are bound and the sigterm handler is installed; its existence is a definitive "ready to accept" signal. The file is closed after the write, so there is no buffering window and no exclusive lock for a poller to fight. Configure `PidFile` in `sshd_config`, drop `-d -d -d` (sshd explicitly suppresses `PidFile` writes in `debug_flag` mode, see `if (options.pid_file != NULL && !debug_flag)` in `sshd.c`), and poll `sshd.pid` for both existence and non-empty content from `WaitForSshd`. Dropping `-d` also removes its "process one connection and exit" side effect; previous attempts at fixing the flake had to fight that constraint at every turn. An `ssh ... echo hi` probe was abandoned because it consumed sshd's only allowed connection before the actual clone could run (runs/28233821130); a follow-up "poll sshd.log for `Server listening on`" probe was abandoned because sshd's `-E` log file is opened without share-read, so neither AHK's `FileRead`, PowerShell's `Get-Content`, nor MSYS2's `grep.exe` can open it while sshd is alive (runs/28243902161, verified locally with OpenSSH for Windows 9.8.3.0p2). The flip side of long-lived sshd is that sshd outlives the test script body, and the next thing the script does is `CleanUpWorkTree` which `DirDelete`s the worktree out from under sshd's still-open `sshd.pid` and `sshd.log` handles. That hangs on Windows (observed in runs/28256992298 and locally). Stopping just the PidFile-named PID is not enough either: the existing "Re-start sshd" sites at the verification clone and inside the retry loop launch additional `sshd.exe` instances that survive along with the original, and the PidFile only ever holds the most recently written PID. Enumerate all `sshd*.exe` processes whose `ExecutablePath` lives under the test's OpenSSH directory via `Win32_Process`, `ProcessClose` each one, and wait for it to exit before letting `CleanUpWorkTree` proceed. The WMI filter on both name and executable path keeps the kill scoped to our test and away from any system OpenSSH service on the runner. The `-E sshd.log` argument is kept (with the same absolute `workTree`-anchored path as before) so the debug log is still captured by `Upload test results` for post-mortem analysis; the new probe does not depend on its contents. `LogLevel VERBOSE` in `sshd_config` is kept too, both because `Server listening on` is useful at that level and because making the logging configuration explicit shouldn't depend on which command-line flags happen to be set. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <[email protected]>
dscho
added a commit
that referenced
this pull request
Jun 26, 2026
The Ctrl+C UI test starts up an OpenSSH-for-Windows `sshd.exe` to exercise the SSH-based clone scenarios, and intentionally leaves it running once the test script exits: it has no `Run` wrapper that would tear it down, and the test does not own a clean shutdown path for it. When `actions/upload-artifact` then tries to zip up the `ui-tests` directory, it fails with `EPERM` on `ui-tests/ctrl-c/ssh_host_rsa_key`, because `sshd.exe` still holds an exclusive handle on the host key file, and the entire upload step aborts. That is the failure observed on attempt #1 of the latest CI run on `fix-pcon-grandchild-cons0`. Stop any leftover `sshd.exe` instances before uploading. The runner is ephemeral and dedicated to the job, so identifying the process by name is safe; the actual termination still goes through `Stop-Process -Id` to keep the kill targeted. `if: always()` mirrors the upload step so the cleanup runs whether the test passed or failed. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <[email protected]>
dscho
added a commit
that referenced
this pull request
Jun 27, 2026
The Ctrl+C UI test starts up an OpenSSH-for-Windows `sshd.exe` to exercise the SSH-based clone scenarios, and intentionally leaves it running once the test script exits: it has no `Run` wrapper that would tear it down, and the test does not own a clean shutdown path for it. When `actions/upload-artifact` then tries to zip up the `ui-tests` directory, it fails with `EPERM` on `ui-tests/ctrl-c/ssh_host_rsa_key`, because `sshd.exe` still holds an exclusive handle on the host key file, and the entire upload step aborts. That is the failure observed on attempt #1 of the latest CI run on `fix-pcon-grandchild-cons0`. Stop any leftover `sshd.exe` instances before uploading. The runner is ephemeral and dedicated to the job, so identifying the process by name is safe; the actual termination still goes through `Stop-Process -Id` to keep the kill targeted. `if: always()` mirrors the upload step so the cleanup runs whether the test passed or failed. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <[email protected]>
dscho
added a commit
that referenced
this pull request
Jun 27, 2026
The Ctrl+C UI test launches OpenSSH for Windows' `sshd.exe` via `Run` and then immediately types the `git clone` keystrokes into the PowerShell window. On the current windows-2025 runners, sshd's cold-start can take long enough that by the time `ssh` attempts the TCP connect the listening socket isn't bound yet; the clone never produces `remote:`, the `WaitForRegExInWindowsTerminal` for it times out, and the test fails. This was the failure on attempt #1 of the first CI run on `fix-pcon-grandchild-cons0`. Use sshd's own readiness signal. Per OpenSSH's `sshd.c`, the `PidFile` is `fopen`/`fprintf`/`fclose`'d immediately before the accept loop, after the listen sockets are bound and the sigterm handler is installed; its existence is a definitive "ready to accept" signal. The file is closed after the write, so there is no buffering window and no exclusive lock for a poller to fight. Configure `PidFile` in `sshd_config`, drop `-d -d -d` (sshd explicitly suppresses `PidFile` writes in `debug_flag` mode, see `if (options.pid_file != NULL && !debug_flag)` in `sshd.c`), and poll `sshd.pid` for both existence and non-empty content from `WaitForSshd`. Dropping `-d` also removes its "process one connection and exit" side effect; previous attempts at fixing the flake had to fight that constraint at every turn. An `ssh ... echo hi` probe was abandoned because it consumed sshd's only allowed connection before the actual clone could run (runs/28233821130); a follow-up "poll sshd.log for `Server listening on`" probe was abandoned because sshd's `-E` log file is opened without share-read, so neither AHK's `FileRead`, PowerShell's `Get-Content`, nor MSYS2's `grep.exe` can open it while sshd is alive (runs/28243902161, verified locally with OpenSSH for Windows 9.8.3.0p2). The flip side of long-lived sshd is that sshd outlives the test script body, and the next thing the script does is `CleanUpWorkTree` which `DirDelete`s the worktree out from under sshd's still-open `sshd.pid` and `sshd.log` handles. That hangs on Windows (observed in runs/28256992298 and locally). Stopping just the PidFile-named PID is not enough either: the existing "Re-start sshd" sites at the verification clone and inside the retry loop launch additional `sshd.exe` instances that survive along with the original, and the PidFile only ever holds the most recently written PID. Enumerate all `sshd*.exe` processes whose `ExecutablePath` lives under the test's OpenSSH directory via `Win32_Process`, `ProcessClose` each one, and wait for it to exit before letting `CleanUpWorkTree` proceed. The WMI filter on both name and executable path keeps the kill scoped to our test and away from any system OpenSSH service on the runner. The `-E sshd.log` argument is kept (with the same absolute `workTree`-anchored path as before) so the debug log is still captured by `Upload test results` for post-mortem analysis; the new probe does not depend on its contents. `LogLevel VERBOSE` in `sshd_config` is kept too, both because `Server listening on` is useful at that level and because making the logging configuration explicit shouldn't depend on which command-line flags happen to be set. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.