首页 > 解决方案 > 有没有一种安全的方法可以将非公共方法用作信号处理程序?

问题描述

我正在 PHP 中实现一个 pre-fork tcp 套接字服务器,使用多个子进程、共享内存、信号量和各种信号。

我目前正在为我的信号处理程序使用受保护的方法。

不幸的是,这偶尔会因“无法访问受保护的方法”错误而失败。

我很确定当代码在某个其他类(例如共享内存类)的方法中时传递信号时会发生这种情况。

我更喜欢使用受保护的方法,因为这些方法真的不应该从任何其他用户土地代码中调用。

我的问题是:是否有任何安全的方法可以使用非公共方法作为信号处理程序?

标签: php

解决方案


简短的回答:不。使用非公共方法作为信号处理程序是不安全的。

更长的答案(为什么): 虽然我不是 PHP 内部专家,但多年来我编写了许多自定义 PHP 扩展并且对内部有一定了解,所以我决定通过查看实际涉及的 PHP 函数来研究这个问题。

用户登陆信号处理程序实际上并没有被操作系统调用。

pcntl_signal ()函数将表示用户空间信号处理程序的结构添加到内部列表,然后(通过其他一些调用)将pcntl_signal_handler()内部函数设置为指定信号的实际处理程序。

传递信号时,操作系统调用pcntl_signal_handler() 修改内部信号处理程序表并将全局pending_signals标志设置为 1。如果启用异步信号,它还将全局vm_interrupt标志设置为 1。

在那之后的某个时候,PHP 将调用pcntl_signal_dispatch()的内部版本,该版本会进行一些完整性检查和内务管理,并最终调用call_user_function()内部函数。

As far as I can tell, call_user_function() is used whenever a user land callable is to be called from within PHP (well, call_user_function() is actually a macro that calls _call_user_function_ex()).

The _call_user_function_ex() function sets up a structure and then calls zend_call_function().

zend_call_function() eventually calls zend_is_callable_ex() which makes a number of checks to see if the user land function is callable, including the current scope, and that check fails if the signal is delivered while the application is executing in any scope other than the class in which the signal handler was delivered (a user land database abstraction method or logger, for example).

So no, it is not safe to use a non-public method as a signal handler.


推荐阅读