Skip to content

Commit a6574d5

Browse files
committed
storing and fetching exceptions catched
1 parent 4ae6c3c commit a6574d5

2 files changed

Lines changed: 35 additions & 30 deletions

File tree

vkext/vk_zend.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,19 @@ static zend_always_inline void vk_zend_update_public_property_long(zval *object,
229229
static zend_always_inline void vk_zend_call_known_instance_method(zval *object,
230230
const char * name, size_t name_len, zval *retval_ptr,
231231
uint32_t param_count, zval *params) {
232-
// TODO - if we need PHP 7, add ifdef, like above
233232
zend_object* zobj = Z_OBJ_P(object);
234233
zend_string* method_name = zend_string_init(name, name_len, 0);
235234
zend_function* fun = Z_OBJ_HANDLER_P(object, get_method)(&zobj, method_name, 0);
236235
zend_string_release(method_name);
237-
assert(fun);
236+
if (!fun) {
237+
return; // retval stays UNDEF
238+
}
239+
#if PHP_MAJOR_VERSION >= 8
238240
zend_call_known_instance_method(fun, zobj, retval_ptr, param_count, params);
241+
#else
242+
// TODO - this branch is not tested yet
243+
zend_call_known_instance_method(fun, object, retval_ptr, param_count, params);
244+
#endif
239245
}
240246

241247
#define ZAPI_TO_PP(az) (&(az))

vkext/vkext-rpc-tl-serialization.cpp

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -932,33 +932,21 @@ bool store_function2(VK_ZVAL_API_P arr, zval *fetcher) {
932932
END_TIMER(store_function2)
933933
return false;
934934
}
935-
zend_object* zobj = Z_OBJ_P(arr);
936-
937-
zend_string* method_name = zend_string_init("typedStore", strlen("typedStore"), 0);
938-
zend_function* typedStore = Z_OBJ_HANDLER_P(arr, get_method)(&zobj, method_name, 0);
939-
zend_string_release(method_name);
940-
941-
if (!typedStore) {
942-
fprintf(stderr, "typedStore is not found\n");
943-
END_TIMER(store_function2)
944-
return false;
945-
}
946-
fprintf(stderr, "typedStore is found\n");
947-
zend_call_known_instance_method(typedStore, zobj,
948-
fetcher, // Where to store the return value
949-
0, // Number of parameters (0 in this case)
950-
NULL // Parameter array (NULL if no parameters)
951-
);
935+
vk_zend_call_known_instance_method(arr, "typedStore", strlen("typedStore"), fetcher, 0, NULL);
952936
if (EG(exception)) {
953-
OBJ_RELEASE(EG(exception));
937+
// This behavior is consistent with old code, in this case, query_one will return qid 0
938+
fprintf(stderr, "typedStore exception\n");
939+
_zend_object* old_exception = EG(exception);
954940
EG(exception) = NULL;
941+
OBJ_RELEASE(old_exception);
942+
END_TIMER(store_function2)
943+
return false;
955944
}
956-
fprintf(stderr, "typedStore after call\n");
957-
if (Z_TYPE_P(fetcher) == IS_NULL) {
945+
if (Z_TYPE_P(fetcher) != IS_OBJECT) { // returned null or function not found
946+
fprintf(stderr, "typedStore fetcher type is %d\n", Z_TYPE_P(fetcher));
958947
END_TIMER(store_function2)
959948
return false;
960949
}
961-
assert(Z_TYPE_P(fetcher) == IS_OBJECT);
962950
// when using fetcher, tl_current_function_name will not be accessed. But we set it anyway in case we forgot something.
963951
tl_current_function_name = "typedStore";
964952
END_TIMER(store_function2)
@@ -1446,25 +1434,32 @@ zval *fetch_function2(zval *fetcher) {
14461434
zval exception_zval;
14471435
ZVAL_OBJ(&exception_zval, old_exception);
14481436

1449-
zval message;
1450-
ZVAL_UNDEF(&message);
1451-
vk_zend_call_known_instance_method(&exception_zval, "getMessage", strlen("getMessage"), &message, 0, NULL);
1437+
zval *message;
1438+
VK_ALLOC_INIT_ZVAL(message);
1439+
ZVAL_UNDEF(message);
1440+
vk_zend_call_known_instance_method(&exception_zval, "getMessage", strlen("getMessage"), message, 0, NULL);
14521441
// fprintf(stderr, "getMessage after call %d\n", Z_TYPE(message));
1453-
assert(Z_TYPE(message) == IS_STRING);
1442+
assert(Z_TYPE_P(message) == IS_STRING);
14541443

14551444
OBJ_RELEASE(old_exception);
14561445

14571446
zval *_err = create_php_instance(reqResult_error_class_name);
14581447

1459-
zend_update_property(NULL, Z_OBJ(*_err), "error", strlen("error"), &message);
1460-
zval_ptr_dtor(&message);
1448+
vk_zend_update_public_property_nod(_err, "error", message);
14611449

14621450
// vk_zend_update_public_property_string(_err, "error", "hren");
14631451
vk_zend_update_public_property_long(_err, "error_code", -1000);
1452+
END_TIMER(fetch_function2)
14641453
return _err;
14651454
}
14661455
fprintf(stderr, "typedFetch after call %d\n", Z_TYPE_P(return_value));
1467-
assert(Z_TYPE_P(return_value) == IS_OBJECT);
1456+
if (Z_TYPE_P(return_value) != IS_OBJECT) { // should be never, but that is user code
1457+
zval *_err = create_php_instance(reqResult_error_class_name);
1458+
vk_zend_update_public_property_string(_err, "error", "fetcher->typedFetch() did not return object, as expected");
1459+
vk_zend_update_public_property_long(_err, "error_code", -1000);
1460+
END_TIMER(fetch_function2)
1461+
return _err;
1462+
}
14681463
if (rpc_error.header.has_value()) {
14691464
zval *wrapped_err = create_php_instance(reqResult_header_class_name);
14701465
zval *header_php_repr = convert_rpc_extra_header_to_php_repr(rpc_error.header.value());
@@ -1541,6 +1536,10 @@ void vk_rpc_tl_query_result_impl(struct rpc_queue *Q, double timeout, zval **r)
15411536
}
15421537

15431538
if (do_rpc_get_and_parse(qid, timeout - precise_now) < 0) {
1539+
// TODO - most likely. leak here (of both T and fetcher).
1540+
// But it is difficult to simulate this situation, so
1541+
// we decided to keep leak to avoid double delete in case we
1542+
// failed to completely understand this code.
15441543
continue;
15451544
}
15461545
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"});

0 commit comments

Comments
 (0)