Commit b0c8e27b27b for php

commit b0c8e27b27b5c7676586b126a4e5c2982a46d63c
Author: lazerg <lazerg2@gmail.com>
Date:   Wed Oct 14 00:56:20 2026 +0000

    Fix GH-24308: Preserve syslog handles not opened by PHP (#24310)

    Only close syslog at request shutdown when PHP has opened it, so embedded
    hosts retain their syslog connection across requests that do not use it.

    When syslog() is called before openlog(), explicitly open the connection
    using syslog.ident and syslog.facility, as error_log=syslog already does.
    This tracks the connection for request cleanup and changes the implicit
    syslog() identity and facility to the configured PHP values.

    Add a regression test checking that a connection opened by syslog() is
    closed before the next request.

    Closes #24310

diff --git a/NEWS b/NEWS
index 5bf9f52d661..cb68d41c333 100644
--- a/NEWS
+++ b/NEWS
@@ -130,6 +130,8 @@ PHP                                                                        NEWS
     table). (evankford)

 - Standard:
+  . Fixed bug GH-24308 (Request shutdown calls closelog() even when syslog
+    was not opened by PHP). (lazerg)
   . Fixed bug GH-24399 (usleep() and time_nanosleep() ignore queued APCs on
     Windows). (Nicolas Grekas)
   . Fixed chown() and lchown() failing to resolve user names in ZTS builds
diff --git a/ext/standard/syslog.c b/ext/standard/syslog.c
index c5d73eb008e..37aab54c569 100644
--- a/ext/standard/syslog.c
+++ b/ext/standard/syslog.c
@@ -41,7 +41,9 @@ PHP_MINIT_FUNCTION(syslog)

 PHP_RSHUTDOWN_FUNCTION(syslog)
 {
-	php_closelog();
+	if (PG(have_called_openlog)) {
+		php_closelog();
+	}
 	if (BG(syslog_device)) {
 		free(BG(syslog_device));
 		BG(syslog_device) = NULL;
@@ -102,6 +104,9 @@ PHP_FUNCTION(syslog)
 		Z_PARAM_STR(message)
 	ZEND_PARSE_PARAMETERS_END();

+	if (!PG(have_called_openlog)) {
+		php_openlog(PG(syslog_ident), 0, PG(syslog_facility));
+	}
 	php_syslog_str(priority, message);
 	RETURN_TRUE;
 }
diff --git a/ext/standard/tests/network/gh24308.phpt b/ext/standard/tests/network/gh24308.phpt
new file mode 100644
index 00000000000..bfb50ae95e4
--- /dev/null
+++ b/ext/standard/tests/network/gh24308.phpt
@@ -0,0 +1,44 @@
+--TEST--
+GH-24308 (syslog() without openlog() is closed at request end)
+--SKIPIF--
+<?php
+if (PHP_OS_FAMILY !== 'Linux') die('skip Linux only');
+if (!@is_dir('/proc/self/fd')) die('skip requires /proc/self/fd');
+if (!@stream_socket_client('udg:///dev/log')) die('skip requires /dev/log');
+?>
+--FILE--
+<?php
+$serverCode = <<<'CODE'
+function sockets() {
+    $sockets = [];
+    foreach (scandir('/proc/self/fd') as $fd) {
+        $link = @readlink("/proc/self/fd/$fd");
+        if ($link !== false && str_starts_with($link, 'socket:')) {
+            $sockets[$fd] = $link;
+        }
+    }
+    return $sockets;
+}
+
+if (isset($_GET['syslog'])) {
+    $before = sockets();
+    syslog(LOG_DEBUG, 'GH-24308');
+    echo json_encode(array_diff_assoc(sockets(), $before));
+} else {
+    echo json_encode(sockets());
+}
+CODE;
+
+include __DIR__."/../../../../sapi/cli/tests/php_cli_server.inc";
+php_cli_server_start($serverCode, null, []);
+
+$opened = json_decode(file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . "/?syslog"), true);
+var_dump(count($opened));
+
+$next = json_decode(file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . "/"), true);
+var_dump(array_intersect_assoc($opened, $next));
+?>
+--EXPECT--
+int(1)
+array(0) {
+}