@@ -532,7 +532,7 @@ static zval *create_php_instance(const char *class_name) {
532532 return ci;
533533}
534534
535- static zval *make_query_result_or_error (zval *r, const vkext_rpc::tl::RpcReqError &error, const vkext_rpc::tl::RpcReqResultExtra *header = nullptr , int extra_flags = 0 );
535+ static zval *make_query_result_or_error (zval ** r, const vkext_rpc::tl::RpcReqError &error, const vkext_rpc::tl::RpcReqResultExtra *header = nullptr , int extra_flags = 0 );
536536
537537/* *
538538 * This function extracts ORIGINAL tl name from given php class name.
@@ -924,36 +924,6 @@ inline void tl_debug(const char *s __attribute__((unused)), int n __attribute__(
924924
925925/* {{{ Interface functions */
926926
927- // returns 0 if no typedStore was found, otherwise returns allocated ZVAL with fetcher instance
928- bool store_function2 (VK_ZVAL_API_P arr, zval *fetcher) {
929- ADD_CNT (store_function2)
930- START_TIMER (store_function2)
931- assert (arr);
932- if (Z_TYPE_P (arr) != IS_OBJECT) {
933- END_TIMER (store_function2)
934- return false ;
935- }
936- vk_zend_call_known_instance_method (arr, " typedStore" , strlen (" typedStore" ), fetcher, 0 , NULL );
937- if (EG (exception)) {
938- // This behavior is consistent with old code, in this case, query_one will return qid 0
939- fprintf (stderr, " typedStore exception\n " );
940- _zend_object* old_exception = EG (exception);
941- EG (exception) = NULL ;
942- OBJ_RELEASE (old_exception);
943- END_TIMER (store_function2)
944- return false ;
945- }
946- if (Z_TYPE_P (fetcher) != IS_OBJECT) { // returned null or function not found
947- fprintf (stderr, " typedStore fetcher type is %d\n " , Z_TYPE_P (fetcher));
948- END_TIMER (store_function2)
949- return false ;
950- }
951- // when using fetcher, tl_current_function_name will not be accessed. But we set it anyway in case we forgot something.
952- tl_current_function_name = " typedStore" ;
953- END_TIMER (store_function2)
954- return true ;
955- }
956-
957927struct tl_tree *store_function (VK_ZVAL_API_P arr) {
958928 ADD_CNT (store_function)
959929 START_TIMER (store_function)
@@ -1064,7 +1034,7 @@ struct tl_tree *store_function(VK_ZVAL_API_P arr) {
10641034 return reinterpret_cast <tl_tree *>(res);
10651035}
10661036
1067- zval *fetch_function (struct tl_tree *T) {
1037+ zval ** fetch_function (struct tl_tree *T) {
10681038 ADD_CNT (fetch_function)
10691039 START_TIMER (fetch_function)
10701040#ifdef VLOG
@@ -1087,10 +1057,10 @@ zval *fetch_function(struct tl_tree *T) {
10871057 vkext_rpc::RpcError rpc_error;
10881058 rpc_error.try_fetch ();
10891059 if (rpc_error.error .has_value ()) {
1090- zval *ret = make_query_result_or_error (NULL , rpc_error.error .value (), rpc_error.header .has_value () ? &rpc_error.header .value () : nullptr , rpc_error.flags );
1060+ *_arr = make_query_result_or_error (NULL , rpc_error.error .value (), rpc_error.header .has_value () ? &rpc_error.header .value () : nullptr , rpc_error.flags );
10911061 DEC_REF (T);
10921062 END_TIMER (fetch_function)
1093- return ret ;
1063+ return _arr ;
10941064 }
10951065 tl_parse_restore_pos (pos);
10961066
@@ -1108,55 +1078,28 @@ zval *fetch_function(struct tl_tree *T) {
11081078 VK_ALLOC_INIT_ZVAL (*_arr);
11091079 ZVAL_BOOL (*_arr, 1 );
11101080 }
1111- return * _arr;
1081+ return _arr;
11121082 } else {
11131083 if (*_arr) {
11141084 zval_dtor (*_arr);
11151085 }
11161086 *_arr = make_query_result_or_error (NULL , {TL_ERROR_RESPONSE_SYNTAX, " Can't parse response" });
1117- return * _arr;
1087+ return _arr;
11181088 }
11191089}
11201090
11211091void _extra_dec_ref (struct rpc_query *q) {
1122- if (!q->extra_free ) {
1123- return ;
1124- }
1125- q->extra_free = 0 ;
1126- total_tl_working--;
11271092 if (q->extra ) {
1128- DEC_REF (q->extra );
1129- q->extra = 0 ;
1093+ total_tl_working--;
11301094 }
1131- zval_ptr_dtor (&q->fetcher );
1095+ DEC_REF (q->extra );
1096+ q->extra = 0 ;
1097+ q->extra_free = 0 ;
11321098}
11331099
11341100struct rpc_query *vk_rpc_tl_query_one_impl (struct rpc_connection *c, double timeout, VK_ZVAL_API_P arr, int ignore_answer) {
11351101 do_rpc_clean ();
11361102 START_TIMER (tmp);
1137- zval fetcher;
1138- ZVAL_NULL (&fetcher);
1139- bool fetcher_found = store_function2 (arr, &fetcher);
1140- END_TIMER (tmp);
1141- if (fetcher_found) {
1142- struct rpc_query *q;
1143- if (!(q = do_rpc_send_noflush (c, timeout, ignore_answer))) {
1144- zval_ptr_dtor (&fetcher);
1145- vkext_error (VKEXT_ERROR_NETWORK, " Can't send packet" );
1146- return 0 ;
1147- }
1148- if (q == (struct rpc_query *)1 ) { // answer is ignored
1149- assert (ignore_answer);
1150- zval_ptr_dtor (&fetcher);
1151- return q;
1152- }
1153- assert (!ignore_answer);
1154- ZVAL_COPY_VALUE (&q->fetcher , &fetcher);
1155- q->extra_free = _extra_dec_ref;
1156- total_tl_working++;
1157- return q;
1158- }
1159- START_TIMER (tmp);
11601103 void *res = store_function (arr);
11611104 END_TIMER (tmp);
11621105 if (!res) {
@@ -1175,23 +1118,15 @@ struct rpc_query *vk_rpc_tl_query_one_impl(struct rpc_connection *c, double time
11751118 }
11761119 assert (!ignore_answer);
11771120 q->extra = res;
1178- ZVAL_NULL (&q->fetcher );
11791121 q->extra_free = _extra_dec_ref;
11801122 total_tl_working++;
11811123 return q;
11821124}
11831125
1184- zval *fetch_function2 (zval *fetcher);
1185-
1186- zval *vk_rpc_tl_query_result_one_impl (struct tl_tree *T, zval *fetcher) {
1126+ zval **vk_rpc_tl_query_result_one_impl (struct tl_tree *T) {
11871127 tl_parse_init ();
11881128 START_TIMER (tmp);
1189- zval *r = NULL ;
1190- if (T) {
1191- r = fetch_function (T);
1192- }else {
1193- r = fetch_function2 (fetcher);
1194- }
1129+ zval **r = fetch_function (T);
11951130 // fprintf(stderr, "~~~~ after fetch:\n");
11961131 // php_debug_zval_dump(*r, 1);
11971132 END_TIMER (tmp);
@@ -1417,79 +1352,9 @@ static zval *convert_rpc_extra_header_to_php_repr(const vkext_rpc::tl::RpcReqRes
14171352 return res;
14181353}
14191354
1420- zval *fetch_function2 (zval *fetcher) {
1421- ADD_CNT (fetch_function2)
1422- START_TIMER (fetch_function2)
1423-
1424- assert (fetcher);
1425- assert (Z_TYPE_P (fetcher) == IS_OBJECT);
1426-
1427- vkext_rpc::RpcError rpc_error;
1428- rpc_error.try_fetch ();
1429- if (rpc_error.error .has_value ()) {
1430- zval *ret = make_query_result_or_error (NULL , rpc_error.error .value (), rpc_error.header .has_value () ? &rpc_error.header .value () : nullptr , rpc_error.flags );
1431- END_TIMER (fetch_function2)
1432- return ret;
1433- }
1434-
1435- zval* return_value;
1436- VK_ALLOC_INIT_ZVAL (return_value);
1437- ZVAL_UNDEF (return_value);
1438- vk_zend_call_known_instance_method (fetcher, " typedFetch" , strlen (" typedFetch" ), return_value, 0 , NULL );
1439- if (EG (exception)) {
1440- efree (return_value); // it is UNDEF
1441-
1442- _zend_object * old_exception = EG (exception);
1443- EG (exception) = NULL ;
1444-
1445- zval exception_zval;
1446- ZVAL_OBJ (&exception_zval, old_exception);
1447-
1448- zval *message;
1449- VK_ALLOC_INIT_ZVAL (message);
1450- ZVAL_UNDEF (message);
1451- vk_zend_call_known_instance_method (&exception_zval, " getMessage" , strlen (" getMessage" ), message, 0 , NULL );
1452- // fprintf(stderr, "getMessage after call %d\n", Z_TYPE(message));
1453- assert (Z_TYPE_P (message) == IS_STRING);
1454-
1455- OBJ_RELEASE (old_exception);
1456-
1457- zval *_err = create_php_instance (reqResult_error_class_name);
1458-
1459- vk_zend_update_public_property_nod (_err, " error" , message);
1460-
1461- // vk_zend_update_public_property_string(_err, "error", "hren");
1462- vk_zend_update_public_property_long (_err, " error_code" , -1000 );
1463- END_TIMER (fetch_function2)
1464- return _err;
1465- }
1466- fprintf (stderr, " typedFetch after call %d\n " , Z_TYPE_P (return_value));
1467- if (Z_TYPE_P (return_value) != IS_OBJECT) { // should be never, but that is user code
1468- zval *_err = create_php_instance (reqResult_error_class_name);
1469- vk_zend_update_public_property_string (_err, " error" , " fetcher->typedFetch() did not return object, as expected" );
1470- vk_zend_update_public_property_long (_err, " error_code" , -1000 );
1471- END_TIMER (fetch_function2)
1472- return _err;
1473- }
1474- if (rpc_error.header .has_value ()) {
1475- zval *wrapped_err = create_php_instance (reqResult_header_class_name);
1476- zval *header_php_repr = convert_rpc_extra_header_to_php_repr (rpc_error.header .value ());
1477-
1478- set_field_int (&wrapped_err, rpc_error.flags , " flags" , -1 );
1479- set_field (&wrapped_err, header_php_repr, " extra" , -1 );
1480- set_field (&wrapped_err, return_value, " result" , -1 );
1481- END_TIMER (fetch_function2)
1482- return wrapped_err;
1483- }
1484- zval *wrapped_err = create_php_instance (reqResult_underscore_class_name);
1485- set_field (&wrapped_err, return_value, " result" , -1 );
1486- END_TIMER (fetch_function2)
1487- return wrapped_err;
1488- }
1489-
1490- static zval *make_query_result_or_error (zval *r, const vkext_rpc::tl::RpcReqError &error, const vkext_rpc::tl::RpcReqResultExtra *header, int extra_flags) {
1355+ static zval *make_query_result_or_error (zval **r, const vkext_rpc::tl::RpcReqError &error, const vkext_rpc::tl::RpcReqResultExtra *header, int extra_flags) {
14911356 if (r) {
1492- return r;
1357+ return * r;
14931358 }
14941359 zval *_err;
14951360 switch (typed_mode) {
@@ -1539,22 +1404,13 @@ void vk_rpc_tl_query_result_impl(struct rpc_queue *Q, double timeout, zval **r)
15391404 }
15401405 struct rpc_query *q = rpc_query_get (qid);
15411406 tl_tree *T = reinterpret_cast <tl_tree *>(q->extra );
1542- zval fetcher;
1543- ZVAL_COPY (&fetcher, &q->fetcher );
15441407 tl_current_function_name = q->fun_name ;
1545- if (T) {
1546- INC_REF (T);
1547- }
1408+ INC_REF (T);
15481409
15491410 if (do_rpc_get_and_parse (qid, timeout - precise_now) < 0 ) {
1550- // TODO - most likely. leak here (of both T and fetcher).
1551- // But it is difficult to simulate this situation, so
1552- // we decided to keep leak to avoid double delete in case we
1553- // failed to completely understand this code.
15541411 continue ;
15551412 }
1556- zval *res = make_query_result_or_error (vk_rpc_tl_query_result_one_impl (T, &fetcher), {TL_ERROR_RESPONSE_NOT_FOUND, " Response not found, probably timed out" });
1557- zval_ptr_dtor (&fetcher);
1413+ zval *res = make_query_result_or_error (vk_rpc_tl_query_result_one_impl (T), {TL_ERROR_RESPONSE_NOT_FOUND, " Response not found, probably timed out" });
15581414 vk_add_index_zval_nod (*r, qid, res);
15591415 }
15601416}
@@ -1585,19 +1441,14 @@ void vk_rpc_tl_query_result_one(INTERNAL_FUNCTION_PARAMETERS) {
15851441 double timeout = (argc < 2 ) ? q->timeout : precise_now + parse_zend_double (VK_ZVAL_ARRAY_TO_API_P (z[1 ]));
15861442 END_TIMER (parse);
15871443 auto *T = reinterpret_cast <tl_tree *>(q->extra );
1588- zval fetcher;
1589- ZVAL_COPY (&fetcher, &q->fetcher );
1590- if (T) {
1591- INC_REF (T);
1592- }
1444+ INC_REF (T);
15931445 if (do_rpc_get_and_parse (qid, timeout - precise_now) < 0 ) {
15941446 zval *r = make_query_result_or_error (NULL , {TL_ERROR_RESPONSE_NOT_FOUND, " Response not found, probably timed out" });
15951447 RETVAL_ZVAL (r, false , true );
15961448 efree (r);
15971449 return ;
15981450 }
1599- zval *r = make_query_result_or_error (vk_rpc_tl_query_result_one_impl (T, &fetcher), {TL_ERROR_RESPONSE_NOT_FOUND, " Response not found, probably timed out" });
1600- zval_ptr_dtor (&fetcher);
1451+ zval *r = make_query_result_or_error (vk_rpc_tl_query_result_one_impl (T), {TL_ERROR_RESPONSE_NOT_FOUND, " Response not found, probably timed out" });
16011452 RETVAL_ZVAL (r, false , true );
16021453 efree (r);
16031454}
0 commit comments