php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #65774 no max file descriptor check for events.mechanism = /dev/poll
Submitted: 2013-09-27 16:00 UTC Modified: 2024-07-21 23:08 UTC
Votes:128
Avg. Score:5.0 ± 0.2
Reproduced:127 of 127 (100.0%)
Same Version:127 (100.0%)
Same OS:127 (100.0%)
From: aglarond at gmail dot com Assigned: petk (profile)
Status: Closed Package: FPM related
PHP Version: Irrelevant OS: SmartOS, possibly others
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: aglarond at gmail dot com
New email:
PHP Version: OS:

 

 [2013-09-27 16:00 UTC] aglarond at gmail dot com
Description:
------------
When using PHP-FPM with 'events.mechanism = /dev/poll' and 'pm = dynamic', we noticed that the log would fill with lines like the following:

WARNING: pid 61603, fpm_event_devpoll_wait(), line 166: /dev/poll: ioctl() returns 22


The line referenced refers to sapi/fpm/fpm/events/devpoll.c:

159	        /* wait for inconming event or timeout */
160	        ret = ioctl(dpfd, DP_POLL, &dopoll);
161	
162	        if (ret < 0) {
163	
164	                /* trigger error unless signal interrupt */
165	                if (errno != EINTR) {
166	                        zlog(ZLOG_WARNING, "/dev/poll: ioctl() returns %d", errno);
167	                        return -1;
168	                }
169	        }


Unfortunately, these log entries didn't help us to solve the problem.  They only served to fill the disk, as they were written as quickly as the I/O subsystem allowed.


What did help narrow down the problem was seeing the following entry:

DEBUG: pid 61603, fpm_event_init_main(), line 333: event module is /dev/poll and 1061 fds have been reserved


It seemed we had reached a watermark, as the default maximum number of file descriptors on this system is 1024:

NAME    PRIVILEGE       VALUE    FLAG   ACTION                       RECIPIENT
process.max-file-descriptor
        basic           1.02K       -   deny                             57203
        privileged      65.5K       -   deny                                 -
        system          2.15G     max   deny                                 -


Increasing the number of file descriptors makes the log entries go away:

NAME    PRIVILEGE       VALUE    FLAG   ACTION                       RECIPIENT
process.max-file-descriptor
        basic           65.5K       -   deny                             70867
        privileged      65.5K       -   deny                                 -
        system          2.15G     max   deny                                 -


I propose prefacing the errno check (line 165) with one for EBADF.  I don't have time to write and test a patch right now, to verify that errno is indeed EBADF in this case (error number 22 is EINVAL, but I suspect this is getting passed from the device driver).  The patch should make this check and then probably end the main process.


An alternative is to change fpm_event_init_main in sapi/fpm/fpm/fpm_events.c to end the main process at file descriptor reservation time:

323	        /* count the max number of necessary fds for polling */
324	        max = 1; /* only one FD is necessary at startup for the master process signal pipe */
325	        for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
326	                if (!wp->config) continue;
327	                if (wp->config->catch_workers_output && wp->config->pm_max_children > 0) {
328	                        max += (wp->config->pm_max_children * 2);
329	                }
330	        }
331	
332	        if (module->init(max) < 0) {
333	                zlog(ZLOG_ERROR, "Unable to initialize the event module %s", module->name);
334	                return -1;
335	        }
336	
337	        zlog(ZLOG_DEBUG, "event module is %s and %d fds have been reserved", module->name, max);
338	


Briefly looking at devpool's init function shows checks for allocating enough memory, but doesn't seem to check if the max file descriptors can actually be allocated.  Ideally, a check should be made at this point to see if an OS limit will be hit before even initializing the module.  I don't know if there are any module-specific semantics that would need to be taken into account and preclude a general check in fpm_event_init_main.


The relevant code paths are unchanged for 5.3.27, 5.4.20, 5.5.4, so marking this as version Irrelevant.



Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-10-05 16:38 UTC] felipe@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: fat
 [2017-10-24 07:45 UTC] kalle@php.net
-Status: Assigned +Status: Open -Assigned To: fat +Assigned To:
 [2024-07-21 23:08 UTC] petk@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: petk
 [2024-07-21 23:08 UTC] petk@php.net
In upcoming PHP-8.4 the /dev/poll mechanism has been removed from FPM SAPI in favor of port API. If you still experience this issue or similar, please open a bug report on GitHub https://github.com/php/php-src/issues

Thanks.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 15:01:29 2024 UTC