@@ -87,11 +87,6 @@ ZEND_API void zend_observer_activate(void)
87
87
current_observed_frame = NULL ;
88
88
}
89
89
90
- ZEND_API void zend_observer_deactivate (void )
91
- {
92
- // now empty and unused, but kept for ABI compatibility
93
- }
94
-
95
90
ZEND_API void zend_observer_shutdown (void )
96
91
{
97
92
zend_llist_destroy (& zend_observers_fcall_list );
@@ -112,7 +107,7 @@ static void zend_observer_fcall_install(zend_execute_data *execute_data)
112
107
ZEND_ASSERT (RUN_TIME_CACHE (op_array ));
113
108
zend_observer_fcall_begin_handler * begin_handlers = (zend_observer_fcall_begin_handler * )& ZEND_OBSERVER_DATA (op_array );
114
109
zend_observer_fcall_end_handler * end_handlers = (zend_observer_fcall_end_handler * )begin_handlers + list -> count , * end_handlers_start = end_handlers ;
115
-
110
+
116
111
* begin_handlers = ZEND_OBSERVER_NOT_OBSERVED ;
117
112
* end_handlers = ZEND_OBSERVER_NOT_OBSERVED ;
118
113
@@ -127,7 +122,7 @@ static void zend_observer_fcall_install(zend_execute_data *execute_data)
127
122
* (end_handlers ++ ) = handlers .end ;
128
123
}
129
124
}
130
-
125
+
131
126
// end handlers are executed in reverse order
132
127
for (-- end_handlers ; end_handlers_start < end_handlers ; -- end_handlers , ++ end_handlers_start ) {
133
128
zend_observer_fcall_end_handler tmp = * end_handlers ;
@@ -136,6 +131,65 @@ static void zend_observer_fcall_install(zend_execute_data *execute_data)
136
131
}
137
132
}
138
133
134
+ static bool zend_observer_remove_handler (void * * first_handler , void * old_handler ) {
135
+ size_t registered_observers = zend_observers_fcall_list .count ;
136
+
137
+ void * * last_handler = first_handler + registered_observers - 1 ;
138
+ for (void * * cur_handler = first_handler ; cur_handler <= last_handler ; ++ cur_handler ) {
139
+ if (* cur_handler == old_handler ) {
140
+ if (registered_observers == 1 || (cur_handler == first_handler && cur_handler [1 ] == NULL )) {
141
+ * cur_handler = ZEND_OBSERVER_NOT_OBSERVED ;
142
+ } else {
143
+ if (cur_handler != last_handler ) {
144
+ memmove (cur_handler , cur_handler + 1 , sizeof (cur_handler ) * (last_handler - cur_handler ));
145
+ } else {
146
+ * last_handler = NULL ;
147
+ }
148
+ }
149
+ return true;
150
+ }
151
+ }
152
+ return false;
153
+ }
154
+
155
+ ZEND_API void zend_observer_add_begin_handler (zend_op_array * op_array , zend_observer_fcall_begin_handler begin ) {
156
+ size_t registered_observers = zend_observers_fcall_list .count ;
157
+ zend_observer_fcall_begin_handler * first_handler = (void * )& ZEND_OBSERVER_DATA (op_array ), * last_handler = first_handler + registered_observers - 1 ;
158
+ if (* first_handler == ZEND_OBSERVER_NOT_OBSERVED ) {
159
+ * first_handler = begin ;
160
+ } else {
161
+ for (zend_observer_fcall_begin_handler * cur_handler = first_handler + 1 ; cur_handler <= last_handler ; ++ cur_handler ) {
162
+ if (* cur_handler == NULL ) {
163
+ * cur_handler = begin ;
164
+ return ;
165
+ }
166
+ }
167
+ // there's no space for new handlers, then it's forbidden to call this function
168
+ ZEND_UNREACHABLE ();
169
+ }
170
+ }
171
+
172
+ ZEND_API bool zend_observer_remove_begin_handler (zend_op_array * op_array , zend_observer_fcall_begin_handler begin ) {
173
+ return zend_observer_remove_handler ((void * * )& ZEND_OBSERVER_DATA (op_array ), begin );
174
+ }
175
+
176
+ ZEND_API void zend_observer_add_end_handler (zend_op_array * op_array , zend_observer_fcall_end_handler end ) {
177
+ size_t registered_observers = zend_observers_fcall_list .count ;
178
+ zend_observer_fcall_end_handler * end_handler = (zend_observer_fcall_end_handler * )& ZEND_OBSERVER_DATA (op_array ) + registered_observers ;
179
+ // to allow to preserve the invariant that end handlers are in reverse order of begin handlers, push the new end handler in front
180
+ if (* end_handler != ZEND_OBSERVER_NOT_OBSERVED ) {
181
+ // there's no space for new handlers, then it's forbidden to call this function
182
+ ZEND_ASSERT (end_handler [registered_observers - 1 ] == NULL );
183
+ memmove (end_handler + 1 , end_handler , registered_observers - 1 );
184
+ }
185
+ * end_handler = end ;
186
+ }
187
+
188
+ ZEND_API bool zend_observer_remove_end_handler (zend_op_array * op_array , zend_observer_fcall_end_handler end ) {
189
+ size_t registered_observers = zend_observers_fcall_list .count ;
190
+ return zend_observer_remove_handler ((void * * )& ZEND_OBSERVER_DATA (op_array ) + registered_observers , end );
191
+ }
192
+
139
193
static void ZEND_FASTCALL _zend_observe_fcall_begin (zend_execute_data * execute_data )
140
194
{
141
195
if (!ZEND_OBSERVER_ENABLED ) {
@@ -205,8 +259,7 @@ ZEND_API void ZEND_FASTCALL zend_observer_fcall_end(zend_execute_data *execute_d
205
259
{
206
260
zend_function * func = execute_data -> func ;
207
261
208
- if (!ZEND_OBSERVER_ENABLED
209
- || !ZEND_OBSERVABLE_FN (func -> common .fn_flags )) {
262
+ if (!ZEND_OBSERVER_ENABLED || !ZEND_OBSERVABLE_FN (func -> common .fn_flags )) {
210
263
return ;
211
264
}
212
265
0 commit comments