简体   繁体   English

有没有安全的方法可以将非公共方法用作信号处理程序?

[英]Is there a safe way to use a non-public method as a signal handler?

I am implementing a pre-fork tcp socket server in PHP, working with multiple child processes, shared memory, semaphores, and various signals. 我正在用PHP实现一个分叉的tcp套接字服务器,使用多个子进程,共享内存,信号量和各种信号。

I am currently using protected methods for my signal handlers. 我目前正在为信号处理程序使用受保护的方法。

Unfortunately, this occasionally fails with "cannot access protected method" errors. 不幸的是,这有时会因“无法访问受保护的方法”错误而失败。

I am pretty sure that this happens when the signal is delivered while the code is in a method in some other class (the shared memory class, for example). 我很确定,当代码在其他某个类(例如,共享内存类)的方法中时,在传递信号时会发生这种情况。

I would prefer to use protected methods because these methods really shouldn't be called from any other user land code. 我更喜欢使用受保护的方法,因为这些方法实际上不应从任何其他用户区号中调用。

My question is: Is there any safe way to use non-public methods as signal handlers? 我的问题是:有没有安全的方法可以将非公共方法用作信号处理程序?

Short answer: No. It is not safe to use a non-public method as a signal handler. 简短的答案:不。使用非公共方法作为信号处理程序并不安全。

Longer answer (why): Although I am no PHP internals expert, I have written a number of custom PHP extensions over the years and have some familiarity with the internals so I decided to research this question by looking at the actual PHP functions involved. 更长的答案(为什么):尽管我不是PHP内部专家,但多年来我写了许多自定义PHP扩展,并且对内部有一定的了解,因此我决定通过查看所涉及的实际PHP函数来研究此问题。

User land signal handlers are not actually called by the operating system. 操作系统实际上并未调用用户陆地信号处理程序。

The pcntl_signal() function adds a structure representing the user land signal handler to an internal list and then (through some other calls), sets up the pcntl_signal_handler() internal function as the actual handler for the specified signal. pcntl_signal()函数将表示用户陆地信号处理程序的结构添加到内部列表中,然后(通过其他一些调用)将pcntl_signal_handler()内部函数设置为指定信号的实际处理程序。

When the signal is delivered, the operating system calls pcntl_signal_handler() which modifies the internal signal handler table and sets the global pending_signals flag to one. 当信号传递,操作系统调用pcntl_signal_handler(),它改变了内部信号处理程序表,并设置全局pending_signals标志之一。 If asynchronous signals are enabled it also sets the global vm_interrupt flag to one. 如果启用了异步信号,则还将全局vm_interrupt标志设置为1。

At some point after that, PHP will call the internal version of pcntl_signal_dispatch() which does some sanity checking and house keeping and eventually calls the call_user_function() internal function. 在此之后的某个时刻,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() ). 据我所知,只要在PHP内部调用可调用用户,就会使用call_user_function()call_user_function()实际上是一个调用_call_user_function_ex()的宏)。

The _call_user_function_ex() function sets up a structure and then calls zend_call_function() . _call_user_function_ex()函数设置一个结构,然后调用zend_call_function()

z end_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). z end_call_function()最终调用zend_is_callable_ex() ,这将进行许多检查以查看用户土地功能是否可调用,包括当前范围,并且如果在应用程序在除以下以外的任何范围内执行应用程序时传递了信号,则该检查将失败。传递信号处理程序的类(例如,用户陆地数据库抽象方法或记录器)。

So no, it is not safe to use a non-public method as a signal handler. 所以不,使用非公共方法作为信号处理程序并不安全。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM