Skip to content

Commit daf80a7

Browse files
committed
WIP
1 parent 031b4c6 commit daf80a7

File tree

9 files changed

+135
-149
lines changed

9 files changed

+135
-149
lines changed

Zend/zend_extensions.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ zend_result zend_load_extension(const char *path)
6060
#endif
6161
}
6262

63-
zend_result zend_load_extension_handle(DL_HANDLE handle, const char *path)
63+
zend_result zend_load_extension_handle_ex(DL_HANDLE handle, const char *path, bool unload_on_failure)
6464
{
6565
#if ZEND_EXTENSIONS_SUPPORT
6666
zend_extension *new_extension;
@@ -79,7 +79,9 @@ zend_result zend_load_extension_handle(DL_HANDLE handle, const char *path)
7979
#ifdef ZEND_WIN32
8080
fflush(stderr);
8181
#endif
82-
DL_UNLOAD(handle);
82+
if (unload_on_failure) {
83+
DL_UNLOAD(handle);
84+
}
8385
return FAILURE;
8486
}
8587

@@ -95,7 +97,9 @@ zend_result zend_load_extension_handle(DL_HANDLE handle, const char *path)
9597
#ifdef ZEND_WIN32
9698
fflush(stderr);
9799
#endif
98-
DL_UNLOAD(handle);
100+
if (unload_on_failure) {
101+
DL_UNLOAD(handle);
102+
}
99103
return FAILURE;
100104
} else if (extension_version_info->zend_extension_api_no < ZEND_EXTENSION_API_NO) {
101105
fprintf(stderr, "%s requires Zend Engine API version %d.\n"
@@ -111,7 +115,9 @@ zend_result zend_load_extension_handle(DL_HANDLE handle, const char *path)
111115
#ifdef ZEND_WIN32
112116
fflush(stderr);
113117
#endif
114-
DL_UNLOAD(handle);
118+
if (unload_on_failure) {
119+
DL_UNLOAD(handle);
120+
}
115121
return FAILURE;
116122
}
117123
} else if (strcmp(ZEND_EXTENSION_BUILD_ID, extension_version_info->build_id) &&
@@ -122,15 +128,19 @@ zend_result zend_load_extension_handle(DL_HANDLE handle, const char *path)
122128
#ifdef ZEND_WIN32
123129
fflush(stderr);
124130
#endif
125-
DL_UNLOAD(handle);
131+
if (unload_on_failure) {
132+
DL_UNLOAD(handle);
133+
}
126134
return FAILURE;
127135
} else if (zend_get_extension(new_extension->name)) {
128136
fprintf(stderr, "Cannot load %s - it was already loaded\n", new_extension->name);
129137
/* See http://support.microsoft.com/kb/190351 */
130138
#ifdef ZEND_WIN32
131139
fflush(stderr);
132140
#endif
133-
DL_UNLOAD(handle);
141+
if (unload_on_failure) {
142+
DL_UNLOAD(handle);
143+
}
134144
return FAILURE;
135145
}
136146

@@ -146,6 +156,11 @@ zend_result zend_load_extension_handle(DL_HANDLE handle, const char *path)
146156
#endif
147157
}
148158

159+
zend_result zend_load_extension_handle(DL_HANDLE handle, const char *path)
160+
{
161+
return zend_load_extension_handle_ex(handle, path, true);
162+
}
163+
149164

150165
void zend_register_extension(zend_extension *new_extension, DL_HANDLE handle)
151166
{

Zend/zend_extensions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ ZEND_API void zend_reset_internal_run_time_cache(void);
153153

154154
BEGIN_EXTERN_C()
155155
ZEND_API zend_result zend_load_extension(const char *path);
156+
ZEND_API zend_result zend_load_extension_handle_ex(DL_HANDLE handle, const char *path, bool unload_on_failure);
156157
ZEND_API zend_result zend_load_extension_handle(DL_HANDLE handle, const char *path);
157158
ZEND_API void zend_register_extension(zend_extension *new_extension, DL_HANDLE handle);
158159
ZEND_API zend_extension *zend_get_extension(const char *extension_name);

ext/opcache/ZendAccelerator.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,6 @@ typedef int gid_t;
102102

103103
#include "zend_simd.h"
104104

105-
static zend_extension opcache_extension_entry;
106-
107105
#ifndef ZTS
108106
zend_accel_globals accel_globals;
109107
#else
@@ -2986,6 +2984,16 @@ static void accel_globals_dtor(zend_accel_globals *accel_globals)
29862984
}
29872985
}
29882986

2987+
void zend_accel_init_globals(void)
2988+
{
2989+
#ifdef ZTS
2990+
ts_allocate_fast_id(&accel_globals_id, &accel_globals_offset, sizeof(zend_accel_globals),
2991+
(ts_allocate_ctor) accel_globals_ctor, (ts_allocate_dtor) accel_globals_dtor);
2992+
#else
2993+
accel_globals_ctor(&accel_globals);
2994+
#endif
2995+
}
2996+
29892997
#ifdef HAVE_HUGE_CODE_PAGES
29902998
# ifndef _WIN32
29912999
# include <sys/mman.h>
@@ -3188,19 +3196,8 @@ static void accel_move_code_to_huge_pages(void)
31883196
# endif /* defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE) */
31893197
#endif /* HAVE_HUGE_CODE_PAGES */
31903198

3191-
void start_accel_extension(void)
3192-
{
3193-
zend_register_extension(&opcache_extension_entry, NULL);
3194-
}
3195-
31963199
static int accel_startup(zend_extension *extension)
31973200
{
3198-
#ifdef ZTS
3199-
accel_globals_id = ts_allocate_fast_id(&accel_globals_id, &accel_globals_offset, sizeof(zend_accel_globals), (ts_allocate_ctor) accel_globals_ctor, (ts_allocate_dtor) accel_globals_dtor);
3200-
#else
3201-
accel_globals_ctor(&accel_globals);
3202-
#endif
3203-
32043201
#ifdef HAVE_JIT
32053202
zend_jit_init();
32063203
#endif
@@ -3211,8 +3208,6 @@ static int accel_startup(zend_extension *extension)
32113208
# endif
32123209
#endif
32133210

3214-
zend_accel_register_ini_entries();
3215-
32163211
#ifdef ZEND_WIN32
32173212
if (UNEXPECTED(accel_gen_uname_id() == FAILURE)) {
32183213
zps_startup_failure("Unable to get user name", NULL, accelerator_remove_cb);
@@ -5194,3 +5189,8 @@ static zend_extension opcache_extension_entry = {
51945189
NULL, /* op_array dtor */
51955190
STANDARD_ZEND_EXTENSION_PROPERTIES
51965191
};
5192+
5193+
zend_extension *zend_accel_get_extension_entry(void)
5194+
{
5195+
return &opcache_extension_entry;
5196+
}

ext/opcache/ZendAccelerator.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,8 @@ extern const char *zps_api_failure_reason;
313313

314314
BEGIN_EXTERN_C()
315315

316-
void start_accel_extension(void);
317316
void accel_shutdown(void);
317+
void zend_accel_init_globals(void);
318318
ZEND_RINIT_FUNCTION(zend_accelerator);
319319
zend_result accel_post_deactivate(void);
320320
void zend_accel_schedule_restart(zend_accel_restart_reason reason);
@@ -325,6 +325,7 @@ zend_result validate_timestamp_and_record_ex(zend_persistent_script *persistent_
325325
zend_result zend_accel_invalidate(zend_string *filename, bool force);
326326
zend_result accelerator_shm_read_lock(void);
327327
void accelerator_shm_read_unlock(void);
328+
zend_extension *zend_accel_get_extension_entry(void);
328329

329330
zend_string *accel_make_persistent_key(zend_string *path);
330331
zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type);

ext/opcache/zend_accelerator_module.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -445,17 +445,9 @@ static ZEND_NAMED_FUNCTION(accel_is_readable)
445445

446446
static ZEND_MINIT_FUNCTION(zend_accelerator)
447447
{
448-
start_accel_extension();
449-
450-
return SUCCESS;
451-
}
452-
453-
void zend_accel_register_ini_entries(void)
454-
{
455-
zend_module_entry *module = zend_hash_str_find_ptr_lc(&module_registry,
456-
ACCELERATOR_PRODUCT_NAME, strlen(ACCELERATOR_PRODUCT_NAME));
457-
458-
zend_register_ini_entries_ex(ini_entries, module->module_number, module->type);
448+
(void)type;
449+
zend_accel_init_globals();
450+
return REGISTER_INI_ENTRIES();
459451
}
460452

461453
void zend_accel_override_file_functions(void)

ext/opcache/zend_accelerator_module.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
#define phpext_opcache_ptr &opcache_module_entry
2828
extern zend_module_entry opcache_module_entry;
2929

30-
void zend_accel_register_ini_entries(void);
31-
3230
void zend_accel_override_file_functions(void);
3331

3432
#endif /* _ZEND_ACCELERATOR_MODULE_H */

ext/standard/dl.c

Lines changed: 89 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "php_globals.h"
2222
#include "php_ini.h"
2323
#include "ext/standard/info.h"
24+
#include "Zend/zend_extensions.h"
2425

2526
#include "SAPI.h"
2627

@@ -106,16 +107,75 @@ PHPAPI void *php_load_shlib(const char *path, char **errp)
106107
}
107108
/* }}} */
108109

110+
static zend_result php_register_module_entry(
111+
zend_module_entry *(*get_module)(void), void *handle, int type, int start_now, int error_type, zend_module_entry **registered_module)
112+
{
113+
zend_module_entry *module_entry = get_module();
114+
115+
if (registered_module) {
116+
*registered_module = NULL;
117+
}
118+
119+
if (zend_hash_str_exists(&module_registry, module_entry->name, strlen(module_entry->name))) {
120+
zend_error(E_CORE_WARNING, "Module \"%s\" is already loaded", module_entry->name);
121+
return FAILURE;
122+
}
123+
if (module_entry->zend_api != ZEND_MODULE_API_NO) {
124+
php_error_docref(NULL, error_type,
125+
"%s: Unable to initialize module\n"
126+
"Module compiled with module API=%d\n"
127+
"PHP compiled with module API=%d\n"
128+
"These options need to match\n",
129+
module_entry->name, module_entry->zend_api, ZEND_MODULE_API_NO);
130+
return FAILURE;
131+
}
132+
if (strcmp(module_entry->build_id, ZEND_MODULE_BUILD_ID)) {
133+
php_error_docref(NULL, error_type,
134+
"%s: Unable to initialize module\n"
135+
"Module compiled with build ID=%s\n"
136+
"PHP compiled with build ID=%s\n"
137+
"These options need to match\n",
138+
module_entry->name, module_entry->build_id, ZEND_MODULE_BUILD_ID);
139+
return FAILURE;
140+
}
141+
142+
if ((module_entry = zend_register_module_ex(module_entry, type)) == NULL) {
143+
return FAILURE;
144+
}
145+
146+
module_entry->handle = handle;
147+
148+
if ((type == MODULE_TEMPORARY || start_now) && zend_startup_module_ex(module_entry) == FAILURE) {
149+
return FAILURE;
150+
}
151+
152+
if ((type == MODULE_TEMPORARY || start_now) && module_entry->request_startup_func) {
153+
if (module_entry->request_startup_func(type, module_entry->module_number) == FAILURE) {
154+
php_error_docref(NULL, error_type, "Unable to initialize module '%s'", module_entry->name);
155+
return FAILURE;
156+
}
157+
}
158+
159+
if (registered_module) {
160+
*registered_module = module_entry;
161+
}
162+
return SUCCESS;
163+
}
164+
109165
/* {{{ php_load_extension */
110166
PHPAPI int php_load_extension(const char *filename, int type, int start_now)
111167
{
112168
void *handle;
113169
char *libpath;
114-
zend_module_entry *module_entry;
170+
zend_module_entry *module_entry = NULL;
115171
zend_module_entry *(*get_module)(void);
172+
zend_extension *zend_extension_entry;
116173
int error_type, slash_suffix = 0;
117174
char *extension_dir;
118175
char *err1, *err2;
176+
bool module_loaded = false;
177+
bool zend_extension_loaded = false;
178+
bool allow_zend_extension_load = (type == MODULE_PERSISTENT);
119179

120180
if (type == MODULE_PERSISTENT) {
121181
extension_dir = INI_STR("extension_dir");
@@ -173,13 +233,13 @@ PHPAPI int php_load_extension(const char *filename, int type, int start_now)
173233
efree(orig_libpath);
174234
efree(err1);
175235
}
176-
efree(libpath);
177236

178237
#ifdef PHP_WIN32
179238
if (!php_win32_image_compatible(handle, &err1)) {
180239
php_error_docref(NULL, error_type, "%s", err1);
181240
efree(err1);
182241
DL_UNLOAD(handle);
242+
efree(libpath);
183243
return FAILURE;
184244
}
185245
#endif
@@ -189,68 +249,50 @@ PHPAPI int php_load_extension(const char *filename, int type, int start_now)
189249
/* Some OS prepend _ to symbol names while their dynamic linker
190250
* does not do that automatically. Thus we check manually for
191251
* _get_module. */
192-
193252
if (!get_module) {
194253
get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "_get_module");
195254
}
196255

197-
if (!get_module) {
198-
if (DL_FETCH_SYMBOL(handle, "zend_extension_entry") || DL_FETCH_SYMBOL(handle, "_zend_extension_entry")) {
199-
DL_UNLOAD(handle);
200-
php_error_docref(NULL, error_type, "Invalid library (appears to be a Zend Extension, try loading using zend_extension=%s from php.ini)", filename);
201-
return FAILURE;
202-
}
203-
DL_UNLOAD(handle);
204-
php_error_docref(NULL, error_type, "Invalid library (maybe not a PHP library) '%s'", filename);
205-
return FAILURE;
206-
}
207-
module_entry = get_module();
208-
if (zend_hash_str_exists(&module_registry, module_entry->name, strlen(module_entry->name))) {
209-
zend_error(E_CORE_WARNING, "Module \"%s\" is already loaded", module_entry->name);
210-
DL_UNLOAD(handle);
211-
return FAILURE;
256+
zend_extension_entry = (zend_extension *) DL_FETCH_SYMBOL(handle, "zend_extension_entry");
257+
if (!zend_extension_entry) {
258+
zend_extension_entry = (zend_extension *) DL_FETCH_SYMBOL(handle, "_zend_extension_entry");
212259
}
213-
if (module_entry->zend_api != ZEND_MODULE_API_NO) {
214-
php_error_docref(NULL, error_type,
215-
"%s: Unable to initialize module\n"
216-
"Module compiled with module API=%d\n"
217-
"PHP compiled with module API=%d\n"
218-
"These options need to match\n",
219-
module_entry->name, module_entry->zend_api, ZEND_MODULE_API_NO);
220-
DL_UNLOAD(handle);
221-
return FAILURE;
222-
}
223-
if(strcmp(module_entry->build_id, ZEND_MODULE_BUILD_ID)) {
224-
php_error_docref(NULL, error_type,
225-
"%s: Unable to initialize module\n"
226-
"Module compiled with build ID=%s\n"
227-
"PHP compiled with build ID=%s\n"
228-
"These options need to match\n",
229-
module_entry->name, module_entry->build_id, ZEND_MODULE_BUILD_ID);
260+
261+
if (!get_module && zend_extension_entry && !allow_zend_extension_load) {
230262
DL_UNLOAD(handle);
263+
php_error_docref(NULL, error_type, "Invalid library (appears to be a Zend Extension and cannot be loaded via dl()) '%s'", filename);
264+
efree(libpath);
231265
return FAILURE;
232266
}
233267

234-
if ((module_entry = zend_register_module_ex(module_entry, type)) == NULL) {
268+
if (!get_module && !zend_extension_entry) {
235269
DL_UNLOAD(handle);
270+
php_error_docref(NULL, error_type, "Invalid library (maybe not a PHP library) '%s'", filename);
271+
efree(libpath);
236272
return FAILURE;
237273
}
238274

239-
module_entry->handle = handle;
240-
241-
if ((type == MODULE_TEMPORARY || start_now) && zend_startup_module_ex(module_entry) == FAILURE) {
242-
DL_UNLOAD(handle);
243-
return FAILURE;
275+
if (get_module && php_register_module_entry(get_module, handle, type, start_now, error_type, &module_entry) == SUCCESS) {
276+
module_loaded = true;
244277
}
245278

246-
if ((type == MODULE_TEMPORARY || start_now) && module_entry->request_startup_func) {
247-
if (module_entry->request_startup_func(type, module_entry->module_number) == FAILURE) {
248-
php_error_docref(NULL, error_type, "Unable to initialize module '%s'", module_entry->name);
249-
DL_UNLOAD(handle);
250-
return FAILURE;
279+
if (zend_extension_entry && allow_zend_extension_load
280+
&& zend_load_extension_handle_ex(handle, libpath, false) == SUCCESS) {
281+
zend_extension_loaded = true;
282+
if (module_loaded && module_entry) {
283+
/* In dual mode, let Zend extension own this handle. */
284+
module_entry->handle = NULL;
251285
}
252286
}
253-
return SUCCESS;
287+
288+
efree(libpath);
289+
290+
if (module_loaded || zend_extension_loaded) {
291+
return SUCCESS;
292+
}
293+
294+
DL_UNLOAD(handle);
295+
return FAILURE;
254296
}
255297
/* }}} */
256298

0 commit comments

Comments
 (0)