php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77194 php7ts.dll crashing when running embed
Submitted: 2018-11-23 14:08 UTC Modified: 2022-11-27 04:22 UTC
Votes:12
Avg. Score:4.3 ± 0.8
Reproduced:10 of 11 (90.9%)
Same Version:6 (60.0%)
Same OS:8 (80.0%)
From: svbussww at 126 dot com Assigned: cmb (profile)
Status: No Feedback Package: Reproducible crash
PHP Version: 7.2.12 OS: Windows 7
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: svbussww at 126 dot com
New email:
PHP Version: OS:

 

 [2018-11-23 14:08 UTC] svbussww at 126 dot com
Description:
------------
php - 7.2.12
php - 7.3.0RC5

php.ini
No extensions are turned on

Test script:
---------------
Test script http://jxcraft.net/Test.zip, VC12 Project, php7ts.dll From https://windows.php.net/download/ ,not actually working, because I've cutted some parts from working project. Script works from time to time and crashes very often.

Actual result:
--------------
Can't initialize heap: [0x000001e7] Attempt to access invalid address.

Problem event name: APPCRASH
Application Name: Test.exe
Application version: 0.0.0.0
Application time stamp: 5bf4612b
Fault module name: php7ts.dll
Fault module version: 7.2.12.0
Fault module timestamp: 5be3d4fd
Exception code: c0000005
Abnormal offset: 000000000001f648
Operating system version: 6.1.7601.2.1.0.256.1
Locale ID: 2052
Other information 1: e3c7
Additional information 2: e3c7d0ab13feedaa62f1ab674aea779c
Additional information 3: ffa7
Additional information 4: ffa7101e299bb1a426430e84b351f5c2

Patches

Fix-Multi-Thread-Allocation-Alignment-Memory-Failure (last revision 2018-11-29 16:46 UTC by svbussww at 126 dot com)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-11-23 15:38 UTC] ab@php.net
-Status: Open +Status: Feedback
 [2018-11-23 15:38 UTC] ab@php.net
Thanks for the report. First, vc12 is not suitable, if you use 7.2 binaries from php.net. Please compile your project with vc15 (vs2017) and post a backtrace. Depending on it, but likely, we'll need some reproduce, too.

Thanks.
 [2018-11-23 19:52 UTC] svbussww at 126 dot com
-Status: Feedback +Status: 打开
 [2018-11-23 19:52 UTC] svbussww at 126 dot com
This problem also exists in VC15
And the problem exists in 7.0.32 7.1.24 7.2.12 7.3.0RC5 In the version
After php_module_startup call
Calling ts_resource_ex in a newly started thread has a chance to crash
Will not crash if php_module_startup is not called
 [2018-11-23 20:57 UTC] svbussww at 126 dot com
-Status: ?? +Status: Open
 [2018-11-23 20:57 UTC] svbussww at 126 dot com
Stack

php7ts.dll!_emalloc(unsigned __int64 size) Line 2425
php7ts.dll!cwd_globals_ctor(_virtual_cwd_globals * cwd_g) Line 391
php7ts.dll!allocate_new_resource(_tsrm_tls_entry * * thread_resources_ptr, unsigned long thread_id) 行 315
php7ts.dll!ts_resource_ex(int id, unsigned long * th_id) Line 395

Exception

The first chance exception at 0x000007FEE3C9F648 (php7ts.dll) (in Test.exe): 0xC0000005: An access violation occurred while reading location 0x0000000000000000.
There is an unhandled exception at 0x000007FEE3C9F648 (php7ts.dll) (in Test.exe): 0xC0000005: An access violation occurred while reading location 0x0000000000000000.
 [2018-11-23 22:23 UTC] ab@php.net
-Status: Open +Status: Feedback
 [2018-11-23 22:23 UTC] ab@php.net
Thanks for the further info. The embed SAPI has php_embed_startup(), which calls php_module_startup(). If you call it separately, you might be calling it twice. Otherwise, it's not clear to me, what exactly is NULL that it tries to dereference, in emalloc, in cwd_globals_ctor? It would rock, if you could extract only the relevant piece of your code where embed is integrated (just as one file with the corresponding embed only API calls), that one could review. It's otherwise a bit hard to guess, as embed is something that gets integrated into another app and the failures can be specific to that app.

Thanks.
 [2018-11-23 22:49 UTC] svbussww at 126 dot com
-Status: Feedback +Status: Open
 [2018-11-23 22:49 UTC] svbussww at 126 dot com
Call API Step Accurate

in Main

tsrm_startup
sapi_startup
php_embed_startup(Internal call php_module_startup)

CreateThread(Loop call)
....

-------------

in Thread

ts_resource
...
ts_free_thread

-------------

The php_module_startup function determines that it is only called once in php_embed_startup

Test VC++ Code In http://jxcraft.net/Test.cpp

Suitable for PHP7.2.12,php7ts.dll Use officially compiled DLL

All remaining irrelevant code has been removed
 [2018-11-26 15:39 UTC] ab@php.net
Thanks for the further info. Please realize, that you're not using the embed SAPI, but are developing your own. To use embed SAPI, you should link with php7embed.lib and include sapi/embed/php_embed.h. It is fine to develop a custom SAPI as you do, but in that case no bug report against the embed SAPI should be filed.

The code you've posted looks OK at first glance. If you indeed were intended to use the embed SAPI, please check a worky example here https://gist.github.com/paresy/3cbd4c6a469511ac7479aa0e7c42fea7, linked from bug #74011. Unfortunately I don't come to debug your code in near days, so can't tell yet whether it uncovers a bug in PHP.

Thanks.
 [2018-11-26 21:21 UTC] svbussww at 126 dot com
Since my test code is completely from php_embed.c and checked correctly
So in theory, using php7embed.lib should also have this problem.
I will go through the standard usage test, but I still hope that I can pay attention to it.
If the standard method still exists, I will follow up the feedback.
 [2018-11-26 22:16 UTC] svbussww at 126 dot com
The problem persists after using the standard method
Environment is Windows 7 SP1 + VS2017 Enterprise

Test code

DWORD WINAPI ThreadProc(LPVOID lpParameter) {
	ts_resource(0);
	ts_free_thread();
	return 0;
}

int main(){
	php_embed_init(0, NULL);
	for (;;){
		HANDLE Thread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
		if (Thread != NULL) CloseHandle(Thread);
	}
	php_embed_shutdown();
	return 0;
}


Debug

Problem event name: APPCRASH
Application Name: Test.exe
Application version: 0.0.0.0
Application timestamp: 5bfc6f7c
Fault module name: php7ts.dll
Fault module version: 7.2.12.0
Fault module timestamp: 5be3d4fd
Exception code: c0000005
Abnormal offset: 000000000001f648
OS version: 6.1.7601.2.1.0.256.1
Locale ID: 2052
Other information 1:e3c7
Additional information 2:e3c7d0ab13feedaa62f1ab674aea779c
Other information 3: db03
Other information 4: db03925cc4db17c3dff9789e6103f141

Can't initialize heap: [0x000001e7] Attempt to access invalid address.

Exception thrown at 0x000007FEEAD5F648 (in php7ts.dll) (in Test.exe): 0xC0000005: An access violation occurred while reading location 0x0000000000000000.

Stack

php7ts.dll!_emalloc(unsigned __int64 size) Line 2425
php7ts.dll!cwd_globals_ctor(_virtual_cwd_globals * cwd_g) Line 391
php7ts.dll!allocate_new_resource(_tsrm_tls_entry * * thread_resources_ptr, unsigned long thread_id) Line 315
php7ts.dll!ts_resource_ex(int id, unsigned long * th_id) Line 395
Test.exe!ThreadProc(void * lpParameter) Line 9
 [2018-11-27 12:03 UTC] svbussww at 126 dot com
Can't initialize heap: [0x000001e7] Attempt to access invalid address.

Tracking source code is generated from zend_alloc.c

in zend_mm_mmap_fixed
VirtualAlloc Error return NULL
 [2018-11-27 12:46 UTC] svbussww at 126 dot com
The bug has been found

file Zend/zend_alloc.c
function zend_mm_chunk_alloc_int
zend_mm_mmap After not aligned
zend_mm_mmap_fixed Call failed is return 0

The cause of the bug
zend_mm_mmap The allocated memory address is released. In the case of multithreading, it may be preempted by other threads.
This causes the subsequent zend_mm_mmap_fixed function to allocate memory and cause the program to crash.

Temporary solution

static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
{
	LOOP:;
	void *ptr = zend_mm_mmap(size);

	if (ptr == NULL) {
		return NULL;
	} else if (ZEND_MM_ALIGNED_OFFSET(ptr, alignment) == 0) {
#ifdef MADV_HUGEPAGE
	    madvise(ptr, size, MADV_HUGEPAGE);
#endif
		return ptr;
	} else {
		size_t offset;

		/* chunk has to be aligned */
		zend_mm_munmap(ptr, size);
		ptr = zend_mm_mmap(size + alignment - REAL_PAGE_SIZE);
#ifdef _WIN32
		offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
		zend_mm_munmap(ptr, size + alignment - REAL_PAGE_SIZE);
		ptr = zend_mm_mmap_fixed((void*)((char*)ptr + (alignment - offset)), size);
		if(ptr == NULL) goto LOOP;
		offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
		if (offset != 0) {
			zend_mm_munmap(ptr, size);
			return NULL;
		}
		return ptr;
#else
		offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
		if (offset != 0) {
			offset = alignment - offset;
			zend_mm_munmap(ptr, offset);
			ptr = (char*)ptr + offset;
			alignment -= offset;
		}
		if (alignment > REAL_PAGE_SIZE) {
			zend_mm_munmap((char*)ptr + size, alignment - REAL_PAGE_SIZE);
		}
# ifdef MADV_HUGEPAGE
	    madvise(ptr, size, MADV_HUGEPAGE);
# endif
#endif
		return ptr;
	}
}

I hope the development team can solve this bug as soon as possible.
 [2018-11-27 13:41 UTC] svbussww at 126 dot com
Fix the temporary plan

static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
{
	void *ptr = zend_mm_mmap(size);

	if (ptr == NULL) {
		return NULL;
	} else if (ZEND_MM_ALIGNED_OFFSET(ptr, alignment) == 0) {
#ifdef MADV_HUGEPAGE
	    madvise(ptr, size, MADV_HUGEPAGE);
#endif
		return ptr;
	} else {
		size_t offset;

		/* chunk has to be aligned */
		zend_mm_munmap(ptr, size);
		LOOP:;
		ptr = zend_mm_mmap(size + alignment - REAL_PAGE_SIZE);
		if (ptr == NULL) return NULL;
#ifdef _WIN32
		offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
		zend_mm_munmap(ptr, size + alignment - REAL_PAGE_SIZE);
		ptr = zend_mm_mmap_fixed((void*)((char*)ptr + (alignment - offset)), size);
		if(ptr == NULL) goto LOOP;
		offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
		if (offset != 0) {
			zend_mm_munmap(ptr, size);
			return NULL;
		}
		return ptr;
#else
		offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
		if (offset != 0) {
			offset = alignment - offset;
			zend_mm_munmap(ptr, offset);
			ptr = (char*)ptr + offset;
			alignment -= offset;
		}
		if (alignment > REAL_PAGE_SIZE) {
			zend_mm_munmap((char*)ptr + size, alignment - REAL_PAGE_SIZE);
		}
# ifdef MADV_HUGEPAGE
	    madvise(ptr, size, MADV_HUGEPAGE);
# endif
#endif
		return ptr;
	}
}
 [2018-11-29 16:49 UTC] svbussww at 126 dot com
I have uploaded a fix.
Use _aligned_malloc and _aligned_free instead of unreliable VirtualAlloc and VirtualFree
 [2018-12-07 11:01 UTC] jr at concept-br dot de
Same Problem here also in 7.2.13 on Windows Server 2012 R2. We restart the apache service every hour to "workaround" until a bugfix is released
 [2018-12-09 17:02 UTC] ab@php.net
@jr at concept-br dot de, please post a backtrace.

Thanks.
 [2019-01-22 08:08 UTC] jr at concept-br dot de
Change from 32 build to 64 build (Apache + PHP) >> Works like a charm!
 [2019-02-14 18:13 UTC] ab@php.net
I don't think the patch is the right solution to this after all. The issue seems to be very specific and affect some specific system configuration. In fact, i couldn't confirm there are issues with the memory manager. The change as in the patch would introduce memory fragmentation in opposite to VirtualAlloc, which would affect performance. 32-bit might be well more affected, but from the backtraces the build used seems to be actually 64-bit. Given Windows 7 reaches EOL in less than a year and such issues are not massively reported, probably the issue is a low priority.

Thanks.
 [2019-10-11 23:59 UTC] jake at qzdesign dot co dot uk
I think there is a heap corruption issue in PHP, at least in the Windows (x64) build.

I've got some complex tests (running via PHPUnit), and I hit this issue almost every time.  Sometimes the tests will run to completion, but most times they'll crash at some different point.  It will be an APPCRASH at one of about three or four apparently random points in the process.  And always at the same address in php7ts.dll.

As I'm sure you can understand, it's difficult to isolate this further.  I can confirm it happens with both PHP 7.1.30 and 7.3.4.

This is further frustrated by a Windows 10 update (yes, I know, we need to stop these forced updates from Microsoft, but easier said than done) to version 1903 (18362.418) which appears to silence APPCRASH: it no longer appears in the Event Log, and Composer is unable to detect the 'return value' exception code but is forced to exit silently itself.

Any suggestions on how to restore logging of APPCRASH events since this latest Microsoft atrocity would be welcomed...
 [2019-10-12 00:19 UTC] jake at qzdesign dot co dot uk
Some comments suggest multithreading issue.  Any way to run Composer/PHP restricted to one thread (with multithreaded install)?  Could try that and see if problem goes away.  Won't be conclusive but might provide clue.
 [2019-10-12 22:38 UTC] jake at qzdesign dot co dot uk
Seems with XDebug enabled, I at least get "Script phpunit ... handling the ... event returned with error code -1073741819" from Composer.  But still can't find anything in Event Viewer since latest Windows update.

This isn't AFAIAA running multithreaded, though is with the MT dist.  We're not actively using ext-pthreads (and not at all unless enabled in the default `php.ini`).

I've tried doubling `memory_limit` and it makes no difference.

My issue might not be the same but does at this stage appear related (though the  OP states "running embed").  It's the closest-matching existing issue I could find, and it's a similar-looking crash in php7ts.dll.  Like I said, heap corruption coming from somewhere??
 [2022-11-17 13:24 UTC] cmb@php.net
-Status: Open +Status: Feedback -Assigned To: +Assigned To: cmb
 [2022-11-17 13:24 UTC] cmb@php.net
This might have the same root cause than GH-9650[1], and as such
would be fixed now.  Can you please check that out?

[1] <https://github.com/php/php-src/issues/9650>
 [2022-11-27 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Dec 12 05:01:28 2024 UTC