From 67d5f39a47b15e28293d9d6558b80ded049179fe Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 1 Nov 2017 15:19:31 +0300 Subject: [PATCH] Persistent resources are "thread-local". Register persistent resources through new functions zend_register_persistent_resource()/zend_register_persistent_resource_ex(). --- UPGRADING.INTERNALS | 5 +++++ Zend/zend_list.c | 30 ++++++++++++++++++++++++++++++ Zend/zend_list.h | 3 +++ ext/dba/dba.c | 5 +---- ext/interbase/interbase.c | 7 +------ ext/mysqli/mysqli_nonapi.c | 6 ++---- ext/oci8/oci8.c | 12 ++++++++++++ ext/odbc/php_odbc.c | 8 +------- ext/pdo/pdo_dbh.c | 11 ++--------- ext/pgsql/pgsql.c | 6 +----- main/streams/streams.c | 7 +------ 11 files changed, 59 insertions(+), 41 deletions(-) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index b36e45fc9d..59ac0bbadc 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -16,6 +16,7 @@ PHP 7.2 INTERNALS UPGRADE NOTES m. AST and IS_CONSTANT n. GC_REFCOUNT() o. zend_get_parameters() + p. zend_register_persistent_resource() 2. Build system changes a. Unix build system changes @@ -112,6 +113,10 @@ PHP 7.2 INTERNALS UPGRADE NOTES o. The zend_get_parameters() and zend_get_parameters_ex() functions were removed. Instead zend_parse_parameters() should be used. + p. New functions zend_register_persistent_resource() or + zend_register_persistent_resource_ex() should beused to register + persistent resources, instead of manual insertion into EG(persistent_list). + ======================== 2. Build system changes ======================== diff --git a/Zend/zend_list.c b/Zend/zend_list.c index 25e185946e..c3401d85c0 100644 --- a/Zend/zend_list.c +++ b/Zend/zend_list.c @@ -337,6 +337,36 @@ const char *zend_rsrc_list_get_rsrc_type(zend_resource *res) } } +ZEND_API zend_resource* zend_register_persistent_resource_ex(zend_string *key, void *rsrc_pointer, int rsrc_type) +{ + zval *zv; + zval tmp; + + ZVAL_NEW_PERSISTENT_RES(&tmp, -1, rsrc_pointer, rsrc_type); + GC_MAKE_PERSISTENT_LOCAL(Z_COUNTED(tmp)); + GC_MAKE_PERSISTENT_LOCAL(key); + + zv = zend_hash_update(&EG(persistent_list), key, &tmp); + if (UNEXPECTED(zv == NULL)) { + free(Z_RES(tmp)); + return NULL; + } + + return Z_RES_P(zv); +} + +ZEND_API zend_resource* zend_register_persistent_resource(const char *key, size_t key_len, void *rsrc_pointer, int rsrc_type) +{ + zend_string *str = zend_string_init(key, key_len, 1); + zend_resource *ret = zend_register_persistent_resource_ex(str, rsrc_pointer, rsrc_type); + + if (UNEXPECTED(ret == NULL)) { + free(str); + } + + return ret; +} + /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_list.h b/Zend/zend_list.h index 2d6535c805..cc813be557 100644 --- a/Zend/zend_list.h +++ b/Zend/zend_list.h @@ -68,6 +68,9 @@ ZEND_API void *zend_fetch_resource2_ex(zval *res, const char *resource_type_name ZEND_API const char *zend_rsrc_list_get_rsrc_type(zend_resource *res); ZEND_API int zend_fetch_list_dtor_id(const char *type_name); +ZEND_API zend_resource* zend_register_persistent_resource(const char *key, size_t key_len, void *rsrc_pointer, int rsrc_type); +ZEND_API zend_resource* zend_register_persistent_resource_ex(zend_string *key, void *rsrc_pointer, int rsrc_type); + extern ZEND_API int le_index_ptr; /* list entry type for index pointers */ END_EXTERN_C() diff --git a/ext/dba/dba.c b/ext/dba/dba.c index 671cb293e3..9da1ba500e 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -997,10 +997,7 @@ restart: info->argv = NULL; if (persistent) { - zval new_le; - - ZVAL_NEW_PERSISTENT_RES(&new_le, -1, info, le_pdb); - if (zend_hash_str_update(&EG(persistent_list), key, keylen, &new_le) == NULL) { + if (zend_register_persistent_resource(key, keylen, info, le_pdb) == NULL) { dba_close(info); php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Could not register persistent resource"); FREENOW; diff --git a/ext/interbase/interbase.c b/ext/interbase/interbase.c index f944c0e4c4..e777962f53 100644 --- a/ext/interbase/interbase.c +++ b/ext/interbase/interbase.c @@ -991,18 +991,13 @@ static void _php_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* ib_link = (ibase_db_link *) emalloc(sizeof(ibase_db_link)); RETVAL_RES(zend_register_resource(ib_link, le_link)); } else { - zend_resource new_le; - ib_link = (ibase_db_link *) malloc(sizeof(ibase_db_link)); if (!ib_link) { RETURN_FALSE; } /* hash it up */ - new_le.type = le_plink; - new_le.ptr = ib_link; - if (zend_hash_str_update_mem(&EG(persistent_list), hash, sizeof(hash)-1, - (void *) &new_le, sizeof(zend_resource)) == NULL) { + if (zend_register_persistent_resource(hash, sizeof(hash)-1, ib_link, le_plink) == NULL) { free(ib_link); RETURN_FALSE; } diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c index 6d4f648a7f..9384b9355a 100644 --- a/ext/mysqli/mysqli_nonapi.c +++ b/ext/mysqli/mysqli_nonapi.c @@ -196,12 +196,10 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_real_conne } while (0); } } else { - zend_resource le; - le.type = php_le_pmysqli(); - le.ptr = plist = calloc(1, sizeof(mysqli_plist_entry)); + plist = calloc(1, sizeof(mysqli_plist_entry)); zend_ptr_stack_init_ex(&plist->free_links, 1); - zend_hash_str_update_mem(&EG(persistent_list), ZSTR_VAL(hash_key), ZSTR_LEN(hash_key), &le, sizeof(le)); + zend_register_persistent_resource(ZSTR_VAL(hash_key), ZSTR_LEN(hash_key), plist, php_le_pmysqli()); } } } diff --git a/ext/oci8/oci8.c b/ext/oci8/oci8.c index 9d65685170..20734d8f88 100644 --- a/ext/oci8/oci8.c +++ b/ext/oci8/oci8.c @@ -2041,8 +2041,10 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char /* add to the appropriate hash */ if (connection->is_persistent) { +#if PHP_VERSION_ID < 70300 new_le.ptr = connection; new_le.type = le_pconnection; +#endif connection->used_this_request = 1; PHP_OCI_REGISTER_RESOURCE(connection, le_pconnection); @@ -2053,7 +2055,11 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char if (OCI_G(old_oci_close_semantics)) { GC_ADDREF(connection->id); } +#if PHP_VERSION_ID < 70300 zend_hash_update_mem(&EG(persistent_list), connection->hash_key, (void *)&new_le, sizeof(zend_resource)); +#else + zend_register_persistent_resource_ex(connection->hash_key, connection, le_pconnection); +#endif OCI_G(num_persistent)++; OCI_G(num_links)++; } else if (!exclusive) { @@ -2874,7 +2880,9 @@ static php_oci_spool *php_oci_get_spool(char *username, int username_len, char * { smart_str spool_hashed_details = {0}; php_oci_spool *session_pool = NULL; +#if PHP_VERSION_ID < 70300 zend_resource spool_le = {{0}}; +#endif zend_resource *spool_out_le = NULL; zend_bool iserror = 0; zval *spool_out_zv = NULL; @@ -2921,10 +2929,14 @@ static php_oci_spool *php_oci_get_spool(char *username, int username_len, char * iserror = 1; goto exit_get_spool; } +#if PHP_VERSION_ID < 70300 spool_le.ptr = session_pool; spool_le.type = le_psessionpool; PHP_OCI_REGISTER_RESOURCE(session_pool, le_psessionpool); zend_hash_update_mem(&EG(persistent_list), session_pool->spool_hash_key, (void *)&spool_le, sizeof(zend_resource)); +#else + zend_register_persistent_resource_ex(session_pool->spool_hash_key, session_pool, le_psessionpool); +#endif } else if (spool_out_le->type == le_psessionpool && ZSTR_LEN(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key) == ZSTR_LEN(spool_hashed_details.s) && memcmp(ZSTR_VAL(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key), ZSTR_VAL(spool_hashed_details.s), ZSTR_LEN(spool_hashed_details.s)) == 0) { diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index be8fd12e11..8bfa5b3dad 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -2571,8 +2571,6 @@ try_and_get_another_connection: /* the link is not in the persistent list */ if ((le = zend_hash_str_find_ptr(&EG(persistent_list), hashed_details, hashed_len)) == NULL) { - zend_resource new_le; - if (ODBCG(max_links) != -1 && ODBCG(num_links) >= ODBCG(max_links)) { php_error_docref(NULL, E_WARNING, "Too many open links (%ld)", ODBCG(num_links)); efree(hashed_details); @@ -2589,11 +2587,7 @@ try_and_get_another_connection: RETURN_FALSE; } - new_le.type = le_pconn; - new_le.ptr = db_conn; - new_le.handle = -1; - if (zend_hash_str_update_mem(&EG(persistent_list), hashed_details, hashed_len, &new_le, - sizeof(zend_resource)) == NULL) { + if (zend_register_persistent_resource(hashed_details, hashed_len, db_conn, le_pconn) == NULL) { free(db_conn); efree(hashed_details); RETURN_FALSE; diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index a89276cfce..bfb65f48e2 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -359,18 +359,11 @@ static PHP_METHOD(PDO, dbh_constructor) /* all set */ if (is_persistent) { - zend_resource le; - /* register in the persistent list etc. */ /* we should also need to replace the object store entry, since it was created with emalloc */ - - le.type = php_pdo_list_entry(); - le.ptr = dbh; - GC_SET_REFCOUNT(&le, 1); - - if ((zend_hash_str_update_mem(&EG(persistent_list), - (char*)dbh->persistent_id, dbh->persistent_id_len, &le, sizeof(le))) == NULL) { + if ((zend_register_persistent_resource( + (char*)dbh->persistent_id, dbh->persistent_id_len, dbh, php_pdo_list_entry())) == NULL) { php_error_docref(NULL, E_ERROR, "Failed to register persistent entry"); } } diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index f1bc779cfe..286c862885 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -1357,8 +1357,6 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* try to find if we already have this link in our persistent list */ if ((le = zend_hash_find_ptr(&EG(persistent_list), str.s)) == NULL) { /* we don't */ - zend_resource new_le; - if (PGG(max_links) != -1 && PGG(num_links) >= PGG(max_links)) { php_error_docref(NULL, E_WARNING, "Cannot create new link. Too many open links (" ZEND_LONG_FMT ")", PGG(num_links)); @@ -1385,9 +1383,7 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) } /* hash it up */ - new_le.type = le_plink; - new_le.ptr = pgsql; - if (zend_hash_str_update_mem(&EG(persistent_list), ZSTR_VAL(str.s), ZSTR_LEN(str.s), &new_le, sizeof(zend_resource)) == NULL) { + if (zend_register_persistent_resource(ZSTR_VAL(str.s), ZSTR_LEN(str.s), pgsql, le_plink) == NULL) { goto err; } PGG(num_links)++; diff --git a/main/streams/streams.c b/main/streams/streams.c index 7f130fcb15..1c3a144e9b 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -296,12 +296,7 @@ fprintf(stderr, "stream_alloc: %s:%p persistent=%s\n", ops->label, ret, persiste } if (persistent_id) { - zval tmp; - - ZVAL_NEW_PERSISTENT_RES(&tmp, -1, ret, le_pstream); - - if (NULL == zend_hash_str_update(&EG(persistent_list), persistent_id, - strlen(persistent_id), &tmp)) { + if (NULL == zend_register_persistent_resource(persistent_id, strlen(persistent_id), ret, le_pstream)) { pefree(ret, 1); return NULL; } -- 2.40.0