4

I am investigating a crash which is occurring when our C++ program calls ts_resource(0) in PHP 7.3.4.

The code was written by a developer who has since left the company and I have very little knowledge of PHP. The original code was written for PHP 5.3 and has worked perfectly for years, but when PHP was upgraded to 7.3.4 our program started to crash intermittently. I discovered the crash is caused by a call to tsrm_get_ls_cache() which is returning a nullptr. I have added a check for the nullptr and so stopped the crash but I would like to know why the call to get the resource returns nullptr and what I can do to prevent it. I assume the problem is memory related as it is intermittent.

I am not sure what code to show as the calls to PHP in our code are extensive. The PHP is compiled with ZTS enabled so it multithreaded.

In the initialisation stage the thread safe manager is started with:

tsrm_startup(128, 1, 0, NULL);
ts_resource(0);
ZEND_TSRMLS_CACHE_UPDATE();

and our Execute function which is called each time PHP code is called starts with:

ts_resource(0);
ZEND_TSRMLS_CACHE_UPDATE();

if (tsrm_get_ls_cache() == nullptr)
    return false;

ExecuteContext context;
context.pOutputStream = pOutputStream;

SG(server_context) = (void*)&context;

Next some initialisation of the context class is carried out before calling php_request_startup(TSRMLS_C);

When the call to get resource fails, the actual failure occurs because malloc fails: The call to ts_resource(0) at the beginning of the Execute function calls into the following PHP function to allocate new resource:

allocate_new_resource(&thread_resources->next, thread_id);

and this call to malloc fails the allocation

static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_T thread_id) { (*thread_resources_ptr) = (tsrm_tls_entry *) malloc(sizeof(tsrm_tls_entry)); ...

If anyone can suggest any reasons why the resource allocation might be failing I would be very grateful.

KRag
  • 51
  • 3
  • have you checked [TSRM_ERROR](https://github.com/php/php-src/blob/PHP-7.3.4/TSRM/TSRM.c) debug logs? – user1597430 Jul 01 '19 at 17:08
  • @user1597430 Thanks for the suggestion. I have added TSRM_DEBUG=1 to the preprocessor settings and updated tsrm_startup(128, 1, TSRM_ERROR_LEVEL_INFO, "D:\\temp\\PHP_log\\debug.txt"); but the debug file is not created. Running in debug mode I can step into the tsrm_error_set function and the code within #if TSRM_DEBUG is jumped over so the file is not set. Any thoughts? – KRag Jul 02 '19 at 09:34
  • try `strace` (for Linux OS only), it may give you some ideas about what is going on with debug file – user1597430 Jul 02 '19 at 19:51
  • Thanks @user1597430, unfortunately I am using Windows – KRag Jul 04 '19 at 07:58
  • I am currently having same issue. Do you have an update on this? – lmilunovic Feb 11 '20 at 13:11
  • Hi @Ladislav92, unfortunately we never solved this. The developer who originally integrated PHP into our product believes it was caused by a threading issue in our code that only became apparent with the upgrade to PHP 7. The work required to investigate the issue and find a solution was deemed too great and so we have stayed with PHP 5.3. Good luck. – KRag Feb 12 '20 at 14:16

1 Answers1

0

Have you tried to use TSRMLS_CACHE_UPDATE instead of ZEND_TSRMLS_CACHE_UPDATE (notice ZEND_ prefix )?

So, as I have understood TSRMLS_CACHE_DEFINE should be set once per compilation unit. TSRMLS_CACHE_EXTERN should be included in other files and TSRMLS_CACHE_UPDATE should be called when appropriate.

lmilunovic
  • 191
  • 1
  • 10