Merge pull request #409 from h2o/gfx/ci-openssl3

ci: use Ubuntu 22.04 to test picotls with OpenSSL 3.0
diff --git a/src/esni.c b/src/esni.c
index 7ec29fb..bf8aa24 100644
--- a/src/esni.c
+++ b/src/esni.c
@@ -36,6 +36,9 @@
 #include <time.h>
 #define OPENSSL_API_COMPAT 0x00908000L
 #include <openssl/err.h>
+#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/provider.h>
+#endif
 #include <openssl/engine.h>
 #include <openssl/pem.h>
 #include "picotls.h"
@@ -134,7 +137,9 @@
     char const *file_output = NULL;
     ERR_load_crypto_strings();
     OpenSSL_add_all_algorithms();
-#if !defined(OPENSSL_NO_ENGINE)
+#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x30000000L
+    (void) OSSL_PROVIDER_load(NULL, "default");
+#elif !defined(OPENSSL_NO_ENGINE)
     /* Load all compiled-in ENGINEs */
     ENGINE_load_builtin_engines();
     ENGINE_register_all_ciphers();
diff --git a/t/cli.c b/t/cli.c
index c937784..892a6e7 100644
--- a/t/cli.c
+++ b/t/cli.c
@@ -158,7 +158,7 @@
                         /* ok */
                     } else {
                         if (encbuf.off != 0)
-                            (void)write(sockfd, encbuf.base, encbuf.off);
+                            repeat_while_eintr(write(sockfd, encbuf.base, encbuf.off), { break; });
                         fprintf(stderr, "ptls_handshake:%d\n", ret);
                         goto Exit;
                     }
@@ -167,7 +167,7 @@
                         if (rbuf.off != 0) {
                             data_received += rbuf.off;
                             if (input_file != input_file_is_benchmark)
-                                write(1, rbuf.base, rbuf.off);
+                                repeat_while_eintr(write(1, rbuf.base, rbuf.off), { goto Exit; });
                             rbuf.off = 0;
                         }
                     } else if (ret == PTLS_ERROR_IN_PROGRESS) {
@@ -254,7 +254,10 @@
                     fprintf(stderr, "ptls_send_alert:%d\n", ret);
                 }
                 if (wbuf.off != 0)
-                    (void)write(sockfd, wbuf.base, wbuf.off);
+                    repeat_while_eintr(write(sockfd, wbuf.base, wbuf.off), {
+                        ptls_buffer_dispose(&wbuf);
+                        goto Exit;
+                    });
                 ptls_buffer_dispose(&wbuf);
                 shutdown(sockfd, SHUT_WR);
             }
diff --git a/t/openssl.c b/t/openssl.c
index fd7a3de..acff973 100644
--- a/t/openssl.c
+++ b/t/openssl.c
@@ -36,6 +36,7 @@
 #include "picotls.h"
 #include "picotls/minicrypto.h"
 #include "../deps/picotest/picotest.h"
+#undef OPENSSL_API_COMPAT
 #include "../lib/openssl.c"
 #include "test.h"
 
@@ -298,18 +299,18 @@
 
     ERR_load_crypto_strings();
     OpenSSL_add_all_algorithms();
-#if !defined(OPENSSL_NO_ENGINE)
+
+#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x30000000L
+    /* Explicitly load the legacy provider in addition to default, as we test Blowfish in one of the tests. */
+    OSSL_PROVIDER *legacy = OSSL_PROVIDER_load(NULL, "legacy");
+    OSSL_PROVIDER *dflt = OSSL_PROVIDER_load(NULL, "default");
+#elif !defined(OPENSSL_NO_ENGINE)
     /* Load all compiled-in ENGINEs */
     ENGINE_load_builtin_engines();
     ENGINE_register_all_ciphers();
     ENGINE_register_all_digests();
 #endif
 
-#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x30000000L
-    /* Explicitly load the legacy provider in addition to default, as we test Blowfish in one of the tests. */
-    OSSL_PROVIDER *legacy = OSSL_PROVIDER_load(NULL, "legacy");
-    OSSL_PROVIDER *dflt = OSSL_PROVIDER_load(NULL, "default");
-#endif
 
     subtest("bf", test_bf);
 
diff --git a/t/util.h b/t/util.h
index a77b02d..6c1a9bc 100644
--- a/t/util.h
+++ b/t/util.h
@@ -365,4 +365,21 @@
     return ptls_iovec_init(NULL, 0);
 }
 
+/* The ptls_repeat_while_eintr macro will repeat a function call (block) if it is interrupted (EINTR) before completion. If failing
+ * for other reason, the macro executes the exit block, such as either { break; } or { goto Fail; }.
+ */
+#ifdef _WINDOWS
+#define repeat_while_eintr(expr, exit_block)                                                                                       \
+    while ((expr) < 0) {                                                                                                           \
+        exit_block;                                                                                                                \
+    }
+#else
+#define repeat_while_eintr(expr, exit_block)                                                                                       \
+    while ((expr) < 0) {                                                                                                           \
+        if (errno == EINTR)                                                                                                        \
+            continue;                                                                                                              \
+        exit_block;                                                                                                                \
+    }
+#endif
+
 #endif