Repository navigation
Conversation
LamentXU123
left a comment
There was a problem hiding this comment.
I am curious how this will work
#include <sapi/embed/php_embed.h>
int main(int argc, char **argv)
{
php_embed_module.php_ini_ignore = 1;
php_embed_init(argc, argv);
zend_eval_string("syslog(LOG_INFO, 'test');", NULL, "test");
php_embed_shutdown();
return 0;
}|
Good catch, I fixed it in 8cd9f6f. Your example left the socket open: |
LamentXU123
left a comment
There was a problem hiding this comment.
Thank you. can you write a regression test?
|
I added a test in f0ed6aa ( The test does not cover the original case, where the embed host opens syslog itself. run-tests cannot run an embed host. |
|
Thank you adding a test! |
|
Agreed. This PR does not change FPM, it only changes I ran php-fpm with |
|
Real BUG - approve please! |
| PHP_RSHUTDOWN_FUNCTION(syslog) | ||
| { | ||
| php_closelog(); | ||
| if (PG(have_called_openlog) || syslog_called) { |
There was a problem hiding this comment.
We shouldn't need this extra variable.
I also think the check is simply incorrect: if a host embed already opens the syslog, and the script calls syslog through the host, then syslog_called is set which will close the host syslog, exactly what we tried to prevent; i.e. it reintroduces the issue.
A better fix is to drop syslog_called, and make sure that if syslog is called without PG(have_called_openlog), that it calls php_openlog. However, that's a behaviour change and can't go into a stable branch.
There was a problem hiding this comment.
I dropped syslog_called in 44d80f5. Now syslog() calls php_openlog() with syslog.ident and syslog.facility if the log is not open, so request shutdown only checks have_called_openlog. You are right about the old check. I ran an embed host that calls openlog("host", ...), and a script syslog() closed the host log at request end, same as on base.
A script syslog() still replaces the host log, because libc has one log per process. With this change the message uses the php ident, like error_log = syslog. A host whose requests do not call syslog() keeps its one connection. gh24308.phpt still fails without the change and passes with it.
This changes the ident for syslog() without openlog(). Do you want me to rebase onto master and add an UPGRADING note? The other option is to keep only the have_called_openlog check for PHP-8.4, but then a plain syslog() leaves its socket open until the process exits.
There was a problem hiding this comment.
Thank you! Nice idea, it saves for FreeUnit 1 syscall at least and even more in upcoming "worker mode" on musl
PS: musl closelog() doing close(log_fd); log_fd = -1; without checking (https://github.com/kraj/musl/blob/dd1e63c3638d5f9afb857fccf6ce1415ca5f1b8b/src/misc/syslog.c#L41-L50) so when log_fd == -1 it leads to close(-1) = EBADF, so extra syscall on request
|
The FREEBSD_NTS failure is not caused by this change. The job stopped before the build because the FreeBSD package mirror returned "Not Found". |
The syslog RSHUTDOWN handler called
php_closelog()after every request, even when nothing in the request had opened syslog. In an embedded SAPI, a host that calledopenlog()before running PHP lost its connection when each request ended. PHP already tracks this inPG(have_called_openlog), so the handler now checks it first. Requests that open syslog throughopenlog(),syslog()orerror_log = syslogstill close it at the end.I checked it with an embed host on Debian (glibc). The host opens syslog with
LOG_NDELAYand runs three requests that do not touch syslog. Before the fix, strace shows four connects to/dev/log. After the fix, it shows one. There is no test, because run-tests has no way to drive the embed SAPI with a host-owned handle.Fixes GH-24308