From a054c0bfb95213e0fd37a7f0c59ed29510f2b873 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Mon, 25 Jul 2022 23:05:10 +1200
Subject: [PATCH 3/4] WIP CI support for Cygwin.

ci-os-only: cygwin

See also: d8e78714-dc77-4a64-783f-e863ba4d951f@2ndquadrant.com

https://cirrus-ci.com/task/5145086722834432

XXX This should use a canned Docker image with all the right packages
installed?  But if the larger image is slower to start, then maybe not...
---
 .cirrus.yml                               | 62 +++++++++++++++++++++++
 configure                                 |  2 +-
 configure.ac                              |  2 +-
 src/test/perl/PostgreSQL/Test/Cluster.pm  |  4 +-
 src/test/perl/PostgreSQL/Test/Utils.pm    | 12 +++--
 src/test/recovery/t/020_archive_status.pl |  2 +-
 src/tools/ci/cores_backtrace.sh           | 31 +++++++++++-
 src/tools/ci/pg_ci_base.conf              |  3 ++
 8 files changed, 108 insertions(+), 10 deletions(-)

diff --git a/.cirrus.yml b/.cirrus.yml
index d95ff4bded8..cd4cbf9e5ed 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -477,6 +477,68 @@ task:
       type: text/plain
 
 
+task:
+  name: Windows - Cygwin
+  #XXX only_if: $CIRRUS_CHANGE_MESSAGE =~ '.*\nci-os-only:[^\n]*cygwin.*'
+  timeout_in: 90m
+
+  env:
+    CPUS: 4
+    BUILD_JOBS: 4
+    TEST_JOBS: 1
+    CCACHE_DIR: /tmp/ccache
+    CONFIGURE_FLAGS: --enable-debug --enable-tap-tests --with-ldap --with-ssl=openssl --with-libxml --enable-cassert
+    # --with-gssapi
+    CONFIGURE_CACHE: /tmp/ccache/configure.cache
+    PG_TEST_USE_UNIX_SOCKETS: 1
+    CCACHE_LOGFILE: ccache.log
+    EXTRA_REGRESS_OPTS: --max-connections=1
+    PG_TEST_EXTRA: ldap ssl # disable kerberos
+
+  windows_container:
+    image: cirrusci/windowsservercore:2019
+    os_version: 2019
+    cpu: $CPUS
+    memory: 4G
+
+  setup_additional_packages_script: |
+    choco install -y --no-progress cygwin
+    C:\tools\cygwin\cygwinsetup.exe -q -P cygrunsrv,make,gcc-core,ccache,binutils,libtool,pkg-config,flex,bison,zlib-devel,libxml2-devel,libxslt-devel,libssl-devel,openldap-devel,libreadline-devel,perl,perl-IPC-Run
+    REM libkrb5-devel,krb5-server
+    C:\tools\cygwin\bin\bash.exe --login -c "cygserver-config -y"
+    C:\tools\cygwin\bin\bash.exe --login -c "echo 'kern.ipc.semmni 1024' >> /etc/cygserver.conf"
+    C:\tools\cygwin\bin\bash.exe --login -c "echo 'kern.ipc.semmns 1024' >> /etc/cygserver.conf"
+    C:\tools\cygwin\bin\bash.exe --login -c "net start cygserver"
+
+  sysinfo_script: |
+    chcp
+    systeminfo
+    powershell -Command get-psdrive -psprovider filesystem
+    set
+    C:\tools\cygwin\bin\bash.exe --login -c "id; uname -a; ulimit -a -H; ulimit -a -S; export"
+
+  ccache_cache:
+    folder: C:\tools\cygwin\tmp\ccache
+
+  configure_script:
+    # Try to configure with the cache file, and retry without if it fails, in case the flags changed.
+    - C:\tools\cygwin\bin\bash.exe --login -c "cd '%cd%' && for i in 1 2; do ./configure --cache-file=${CONFIGURE_CACHE} ${CONFIGURE_FLAGS} CC='ccache gcc' CFLAGS='-Og -ggdb' && break; rm -v ${CONFIGURE_CACHE}; done"
+
+  build_script:
+    - C:\tools\cygwin\bin\bash.exe --login -c "cd '%cd%' && make -s -j ${BUILD_JOBS} world-bin"
+    - C:\tools\cygwin\bin\bash.exe --login -c "ccache --show-stats"
+
+  always:
+    upload_caches: ccache
+
+  test_world_script:
+    - C:\tools\cygwin\bin\bash.exe --login -c "cd '%cd%' && timeout 77m make -s -j ${TEST_JOBS} ${CHECK} PROVE_FLAGS='-j2 --timer' ${CHECKFLAGS}"
+
+  on_failure:
+    <<: *on_failure
+    cores_script:
+      - C:\tools\cygwin\bin\bash.exe --login -c "cd '%cd%' && src/tools/ci/cores_backtrace.sh cygwin ."
+
 task:
   name: CompilerWarnings
 
diff --git a/configure b/configure
index 5ea790d6380..f4b761db92d 100755
--- a/configure
+++ b/configure
@@ -16439,7 +16439,7 @@ fi
 
 # mingw has adopted a GNU-centric interpretation of optind/optreset,
 # so always use our version on Windows.
-if test "$PORTNAME" = "win32"; then
+if test "$PORTNAME" = "win32" -o "$PORTNAME" = "cygwin"; then
   case " $LIBOBJS " in
   *" getopt.$ac_objext "* ) ;;
   *) LIBOBJS="$LIBOBJS getopt.$ac_objext"
diff --git a/configure.ac b/configure.ac
index d80cdb5ca25..9b5f8c1cdb4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1877,7 +1877,7 @@ fi
 
 # mingw has adopted a GNU-centric interpretation of optind/optreset,
 # so always use our version on Windows.
-if test "$PORTNAME" = "win32"; then
+if test "$PORTNAME" = "win32" -o "$PORTNAME" = "cygwin"; then
   AC_LIBOBJ(getopt)
   AC_LIBOBJ(getopt_long)
 fi
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index d80134b26f3..5b5e8e67137 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -1052,7 +1052,7 @@ sub enable_restoring
 	# the path contains spaces.
 	$path =~ s{\\}{\\\\}g if ($PostgreSQL::Test::Utils::windows_os);
 	my $copy_command =
-	  $PostgreSQL::Test::Utils::windows_os
+	  $PostgreSQL::Test::Utils::windows_os && !$PostgreSQL::Test::Utils::is_cygwin
 	  ? qq{copy "$path\\\\%f" "%p"}
 	  : qq{cp "$path/%f" "%p"};
 
@@ -1122,7 +1122,7 @@ sub enable_archiving
 	# the path contains spaces.
 	$path =~ s{\\}{\\\\}g if ($PostgreSQL::Test::Utils::windows_os);
 	my $copy_command =
-	  $PostgreSQL::Test::Utils::windows_os
+	  $PostgreSQL::Test::Utils::windows_os && !$PostgreSQL::Test::Utils::is_cygwin
 	  ? qq{copy "%p" "$path\\\\%f"}
 	  : qq{cp "%p" "$path/%f"};
 
diff --git a/src/test/perl/PostgreSQL/Test/Utils.pm b/src/test/perl/PostgreSQL/Test/Utils.pm
index 99d33451064..fb7fca57239 100644
--- a/src/test/perl/PostgreSQL/Test/Utils.pm
+++ b/src/test/perl/PostgreSQL/Test/Utils.pm
@@ -88,10 +88,11 @@ our @EXPORT = qw(
 
   $windows_os
   $is_msys2
+  $is_cygwin
   $use_unix_sockets
 );
 
-our ($windows_os, $is_msys2, $use_unix_sockets, $timeout_default,
+our ($windows_os, $is_msys2, $is_cygwin, $use_unix_sockets, $timeout_default,
 	$tmp_check, $log_path, $test_logfile);
 
 BEGIN
@@ -140,13 +141,18 @@ BEGIN
 	$ENV{PGAPPNAME} = basename($0);
 
 	# Must be set early
-	$windows_os = $Config{osname} eq 'MSWin32' || $Config{osname} eq 'msys';
+	$windows_os = $Config{osname} eq 'MSWin32' || $Config{osname} eq 'msys' ||
+	  $Config{osname} eq 'cygwin';
+
 	# Check if this environment is MSYS2.
 	$is_msys2 =
 	     $windows_os
 	  && -x '/usr/bin/uname'
 	  && `uname -or` =~ /^[2-9].*Msys/;
 
+	# Check if this environment is Cygwin
+	$is_cygwin = $Config{osname} eq 'cygwin';
+
 	if ($windows_os)
 	{
 		require Win32API::File;
@@ -707,7 +713,7 @@ sub dir_symlink
 {
 	my $oldname = shift;
 	my $newname = shift;
-	if ($windows_os)
+	if ($windows_os && !$is_cygwin)
 	{
 		$oldname =~ s,/,\\,g;
 		$newname =~ s,/,\\,g;
diff --git a/src/test/recovery/t/020_archive_status.pl b/src/test/recovery/t/020_archive_status.pl
index 2108d50073a..fd46f45c627 100644
--- a/src/test/recovery/t/020_archive_status.pl
+++ b/src/test/recovery/t/020_archive_status.pl
@@ -26,7 +26,7 @@ my $primary_data = $primary->data_dir;
 # a portable solution, use an archive command based on a command known to
 # work but will fail: copy with an incorrect original path.
 my $incorrect_command =
-  $PostgreSQL::Test::Utils::windows_os
+  $PostgreSQL::Test::Utils::windows_os && !$PostgreSQL::Test::Utils::is_cygwin
   ? qq{copy "%p_does_not_exist" "%f_does_not_exist"}
   : qq{cp "%p_does_not_exist" "%f_does_not_exist"};
 $primary->safe_psql(
diff --git a/src/tools/ci/cores_backtrace.sh b/src/tools/ci/cores_backtrace.sh
index 28d3cecfc67..27f93147e4e 100755
--- a/src/tools/ci/cores_backtrace.sh
+++ b/src/tools/ci/cores_backtrace.sh
@@ -1,5 +1,8 @@
 #! /bin/sh
 
+#set -e
+set -x
+
 if [ $# -ne 2 ]; then
     echo "cores_backtrace.sh <os> <directory>"
     exit 1
@@ -8,9 +11,24 @@ fi
 os=$1
 directory=$2
 
+findargs=''
 case $os in
     freebsd|linux|macos)
-    ;;
+        ;;
+
+    cygwin)
+        # XXX Evidently I don't know how to write two arguments here without pathname expansion later, other than eval.
+        #findargs='-name "*.stackdump"'
+        for stack in $(find "$directory" -type f -name "*.stackdump") ; do
+            binary=`basename "$stack" .stackdump`
+            echo;echo;
+            echo "dumping ${stack} for ${binary}"
+            #awk '/^0/{print $2}' $stack |addr2line -f -i -e "./src/backend/$binary.exe"
+            awk '/^0/{print $2}' $stack |addr2line -f -i -e src/backend/postgres.exe
+        done
+        exit 0
+        ;;
+
     *)
         echo "unsupported operating system ${os}"
         exit 1
@@ -18,7 +36,7 @@ case $os in
 esac
 
 first=1
-for corefile in $(find "$directory" -type f) ; do
+for corefile in $(find "$directory" -type f $findargs) ; do
     if [ "$first" -eq 1 ]; then
         first=0
     else
@@ -28,6 +46,13 @@ for corefile in $(find "$directory" -type f) ; do
 
     if [ "$os" = 'macos' ]; then
         lldb -c $corefile --batch -o 'thread backtrace all' -o 'quit'
+    elif [ "$os" = 'cygwin' ]; then
+        # https://cirrus-ci.com/task/4964259674193920
+        #binary=${corefile%.stackdump}
+        #binary=${corefile#*/}
+        binary=`basename "$corefile" .stackdump`
+        echo "dumping ${corefile} for ${binary}"
+        awk '/^0/{print $2}' $corefile |addr2line -f -i -e ./src/backend/postgres.exe
     else
         auxv=$(gdb --quiet --core ${corefile} --batch -ex 'info auxv' 2>/dev/null)
         if [ $? -ne 0 ]; then
@@ -48,3 +73,5 @@ for corefile in $(find "$directory" -type f) ; do
         gdb --batch --quiet -ex "thread apply all bt full" -ex "quit" "$binary" "$corefile" 2>/dev/null
     fi
 done
+
+exit 0
diff --git a/src/tools/ci/pg_ci_base.conf b/src/tools/ci/pg_ci_base.conf
index d8faa9c26c1..0d43b387006 100644
--- a/src/tools/ci/pg_ci_base.conf
+++ b/src/tools/ci/pg_ci_base.conf
@@ -12,3 +12,6 @@ log_connections = true
 log_disconnections = true
 log_line_prefix = '%m [%p][%b] %q[%a][%v:%x] '
 log_lock_waits = true
+
+data_sync_retry = on
+shared_memory_type = mmap
-- 
2.25.1

