2017-03-27 5 views
1

나는 며칠 동안 신비한 오류로 고심하고있다. PHP 7.1.0RC3을 사용하고 있습니다. ZTS/pthreads를 사용하여을 사용하여 직접 컴파일했습니다. 최근에 저는 Redis로 MySQL을 대체 한 리팩토링터를 개발하여 응용 프로그램에서 디스크가 아닌 데이터 I/O를 최적화했습니다.PHP + PThreads + Redis/Predis = zend_mm_heap가 손상 되었습니까?

각 Cryptocurrency 마켓에 대한 스레드 (A)를 만드는 스크립트가 있습니다. Thread (A)는 각 Trading Strategy에 대해 다른 Thread (B)를 만듭니다. B 스레드는 A 스레드 전에 항상 동기화됩니다.

계속이 오류가 발생합니다 : zend_mm_heap corrupted. 그것은 스크립트를 실행할 때마다 다른 시점에서 실행됩니다.

모든 Google 픽스 수정본을 사용해 보았습니다. 가비지 콜렉션, PHP 구성/컴파일, 모두 상세하게 검토되었습니다. 내가

모든 데이터를 읽고 레디 스에 저장, pthreads 정보와 레디 스/Predis, 다른 "수정"영향을 미치지 않았다 반면 ... "손상 zend_mm_heap"관련 아무것도 발견하지 않았습니다 (Predis를 통해) . 오류 메시지는 스레드 A 또는 스레드 B에서 Predis를 사용할 때만 나타납니다 (매번 변경됨). 두 번의 Predis 메소드 호출이 빠르게 연속적으로 발생하면 (예를 들어 설정), 더 자주 발생합니다.

shell_exec()을 사용하여 CLI를 통해 직접 Redis 명령을 실행하면이 오류가 표시되지 않습니다. 그러나 이것은 상당히 느려서 단순히이 엣지 경우를 놓칠 수 있습니까? 사람이 어떤 입력을 제공 할 수있는 경우

/다음 중 하나를 향한 생각, 나는 크게 감사하겠습니다 :이 내 응용 프로그램에 어디에서 오는

  1. 은 어떻게 찾을 수 있습니까?
  2. 전용 Redis Server가이 문제를 해결할 수 있습니까?
  3. https://github.com/krakjoe/pthreads에게 버그 리포트를 제출해야합니까?
  4. https://github.com/nrk/predis에게 버그 리포트를 제출해야합니까?
  5. 일반적으로 스레드 안전 환경 (일명 : ZTS)에서 zend_mm_heap corrupted이 발생할 수있는 이유를 알고 있습니까? 아니면 어떻게 내가 그것을 지켜야 하는가 ???
  6. 을 컴파일해야합니까? 다른 버전의 PHP 7 이상? https://github.com/php/php-src

나는 옵션이 없습니다. 자비를 베풀어주십시오. 코드 샘플을 공유 할 수 있지만 여기에 붙여 넣는 것은별로 유용하지 않습니다.

편집 나는 ./configure --enable-maintainer-zts --enable-pthreads --with-pthreads-sanitize --with-mysqli --enable-embedded-mysqli와 PHP를 다시 컴파일하고 나는 전에 내가 보지 못한 새로운 오류보고 : 나는 메모리 손상의 원인을 발견

==2716== ERROR: AddressSanitizer: heap-use-after-free on address 0x600800001c15 at pc 0xe25a87 bp 0x7f7a049feae0 sp 0x7f7a049fead0 
READ of size 1 at 0x600800001c15 thread T1632 
    #0 0xe25a86 (/usr/local/bin/php+0xe25a86) 
    #1 0xe953c8 (/usr/local/bin/php+0xe953c8) 
    #2 0xe4935b (/usr/local/bin/php+0xe4935b) 
    #3 0xcbede3 (/usr/local/bin/php+0xcbede3) 
    #4 0x98cfa9 (/usr/local/bin/php+0x98cfa9) 
    #5 0x99dc3c (/usr/local/bin/php+0x99dc3c) 
    #6 0x7f7b57e74a97 (/usr/lib64/libasan.so.0.0.0+0x19a97) 
    #7 0x7f7b5694edc4 (/usr/lib64/libpthread-2.17.so+0x7dc4) 
    #8 0x7f7b5667d73c (/usr/lib64/libc-2.17.so+0xf773c) 
0x600800001c15 is located 5 bytes inside of 48-byte region [0x600800001c10,0x600800001c40) 
freed by thread T1623 here: 
    #0 0x7f7b57e71009 (/usr/lib64/libasan.so.0.0.0+0x16009) 
    #1 0xe259fb (/usr/local/bin/php+0xe259fb) 
    #2 0xe953c8 (/usr/local/bin/php+0xe953c8) 
    #3 0xe4935b (/usr/local/bin/php+0xe4935b) 
    #4 0xcbede3 (/usr/local/bin/php+0xcbede3) 
    #5 0x98cfa9 (/usr/local/bin/php+0x98cfa9) 
    #6 0x99dc3c (/usr/local/bin/php+0x99dc3c) 
    #7 0x7f7b57e74a97 (/usr/lib64/libasan.so.0.0.0+0x19a97) 
previously allocated by thread T0 here: 
    #0 0x7f7b57e71129 (/usr/lib64/libasan.so.0.0.0+0x16129) 
    #1 0xdb0118 (/usr/local/bin/php+0xdb0118) 
    #2 0xe64f6c (/usr/local/bin/php+0xe64f6c) 
    #3 0xe68c5d (/usr/local/bin/php+0xe68c5d) 
    #4 0xcc4dcc (/usr/local/bin/php+0xcc4dcc) 
    #5 0xcc5972 (/usr/local/bin/php+0xcc5972) 
    #6 0x111f82c (/usr/local/bin/php+0x111f82c) 
    #7 0x44c781 (/usr/local/bin/php+0x44c781) 
    #8 0x7f7b565a7b34 (/usr/lib64/libc-2.17.so+0x21b34) 
Thread T1632 created by T0 here: 
    #0 0x7f7b57e65c3a (/usr/lib64/libasan.so.0.0.0+0xac3a) 
    #1 0x99e4cb (/usr/local/bin/php+0x99e4cb) 
    #2 0x975d2a (/usr/local/bin/php+0x975d2a) 
    #3 0x11105c1 (/usr/local/bin/php+0x11105c1) 
    #4 0xf71de2 (/usr/local/bin/php+0xf71de2) 
    #5 0x97b385 (/usr/local/bin/php+0x97b385) 
    #6 0x11126bc (/usr/local/bin/php+0x11126bc) 
    #7 0xf71de2 (/usr/local/bin/php+0xf71de2) 
    #8 0x97b385 (/usr/local/bin/php+0x97b385) 
    #9 0x11126bc (/usr/local/bin/php+0x11126bc) 
    #10 0xf71de2 (/usr/local/bin/php+0xf71de2) 
    #11 0x97b385 (/usr/local/bin/php+0x97b385) 
    #12 0x11126bc (/usr/local/bin/php+0x11126bc) 
    #13 0xf71de2 (/usr/local/bin/php+0xf71de2) 
    #14 0x97b385 (/usr/local/bin/php+0x97b385) 
    #15 0x11126bc (/usr/local/bin/php+0x11126bc) 
    #16 0xf71de2 (/usr/local/bin/php+0xf71de2) 
    #17 0x97b385 (/usr/local/bin/php+0x97b385) 
    #18 0x1110b28 (/usr/local/bin/php+0x1110b28) 
    #19 0xf71de2 (/usr/local/bin/php+0xf71de2) 
    #20 0x97b385 (/usr/local/bin/php+0x97b385) 
    #21 0x11126bc (/usr/local/bin/php+0x11126bc) 
    #22 0xf71de2 (/usr/local/bin/php+0xf71de2) 
    #23 0x97b385 (/usr/local/bin/php+0x97b385) 
    #24 0x111c28a (/usr/local/bin/php+0x111c28a) 
    #25 0xe52281 (/usr/local/bin/php+0xe52281) 
    #26 0xcc766f (/usr/local/bin/php+0xcc766f) 
    #27 0x1121d36 (/usr/local/bin/php+0x1121d36) 
    #28 0x44d202 (/usr/local/bin/php+0x44d202) 
    #29 0x7f7b565a7b34 (/usr/lib64/libc-2.17.so+0x21b34) 
Thread T1623 created by T0 here: 
    #0 0x7f7b57e65c3a (/usr/lib64/libasan.so.0.0.0+0xac3a) 
    #1 0x99e4cb (/usr/local/bin/php+0x99e4cb) 
    #2 0x975d2a (/usr/local/bin/php+0x975d2a) 
    #3 0x11105c1 (/usr/local/bin/php+0x11105c1) 
    #4 0xf71de2 (/usr/local/bin/php+0xf71de2) 
    #5 0x97b385 (/usr/local/bin/php+0x97b385) 
    #6 0x11126bc (/usr/local/bin/php+0x11126bc) 
    #7 0xf71de2 (/usr/local/bin/php+0xf71de2) 
    #8 0x97b385 (/usr/local/bin/php+0x97b385) 
    #9 0x11126bc (/usr/local/bin/php+0x11126bc) 
    #10 0xf71de2 (/usr/local/bin/php+0xf71de2) 
    #11 0x97b385 (/usr/local/bin/php+0x97b385) 
    #12 0x11126bc (/usr/local/bin/php+0x11126bc) 
    #13 0xf71de2 (/usr/local/bin/php+0xf71de2) 
    #14 0x97b385 (/usr/local/bin/php+0x97b385) 
    #15 0x11126bc (/usr/local/bin/php+0x11126bc) 
    #16 0xf71de2 (/usr/local/bin/php+0xf71de2) 
    #17 0x97b385 (/usr/local/bin/php+0x97b385) 
    #18 0x1110b28 (/usr/local/bin/php+0x1110b28) 
    #19 0xf71de2 (/usr/local/bin/php+0xf71de2) 
    #20 0x97b385 (/usr/local/bin/php+0x97b385) 
    #21 0x11126bc (/usr/local/bin/php+0x11126bc) 
    #22 0xf71de2 (/usr/local/bin/php+0xf71de2) 
    #23 0x97b385 (/usr/local/bin/php+0x97b385) 
    #24 0x111c28a (/usr/local/bin/php+0x111c28a) 
    #25 0xe52281 (/usr/local/bin/php+0xe52281) 
    #26 0xcc766f (/usr/local/bin/php+0xcc766f) 
    #27 0x1121d36 (/usr/local/bin/php+0x1121d36) 
    #28 0x44d202 (/usr/local/bin/php+0x44d202) 
    #29 0x7f7b565a7b34 (/usr/lib64/libc-2.17.so+0x21b34) 
Shadow bytes around the buggy address: 
    0x0c017fff8330: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 fa 
    0x0c017fff8340: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa 
    0x0c017fff8350: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 00 
    0x0c017fff8360: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 fa 
    0x0c017fff8370: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 00 
=>0x0c017fff8380: fa fa[fd]fd fd fd fd fd fa fa 00 00 00 00 00 00 
    0x0c017fff8390: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00 
    0x0c017fff83a0: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00 
    0x0c017fff83b0: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00 
    0x0c017fff83c0: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 fa 
    0x0c017fff83d0: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa 
Shadow byte legend (one shadow byte represents 8 application bytes): 
    Addressable:   00 
    Partially addressable: 01 02 03 04 05 06 07 
    Heap left redzone:  fa 
    Heap righ redzone:  fb 
    Freed Heap region:  fd 
    Stack left redzone: f1 
    Stack mid redzone:  f2 
    Stack right redzone: f3 
    Stack partial redzone: f4 
    Stack after return: f5 
    Stack use after scope: f8 
    Global redzone:  f9 
    Global init order:  f6 
    Poisoned by user:  f7 
    ASan internal:   fe 
==2716== ABORTING 

답변

0

을하고 "수정"매우 간단했다 . 나는 pthreads에서 phpiredis $ 클라이언트를 사용하는 유일한 "치명적이지 않은"방법은 명시 적으로 현재 로컬 범위에서 명령/연결을 연결/실행하는 것임을 발견했습니다.

까지 합산 메모리 손상에 다음과 같은 결과 때 높은 부하 : 스레드 환경에서 참조하여 다른 개체에 phpiredis의 $ 클라이언트를 전달하는 시도

  1. 에 phpiredis의 $ 클라이언트를 전달하는 시도
  2. Threaded 컨텍스트에서 값에 의한 다른 객체
  3. Threaded 컨텍스트 (예 : _Redis, 현재 Investor :: save에있는 경우)의 로컬 범위를 제외하고 어디에서나 phpiredis $ 클라이언트를 인스턴스화/사용하려고 시도했습니다.
  4. 시도 중 일에 실수로 phpiredis 연결을 일반적으로 쓰레드 문맥에서 재사용한다.

MySQLi $ 클라이언트를 같은 방법/컨텍스트의 다른 객체에 전달할 때 메모리 손상이 발생하지 않는다.

나는이 다른 사람이 내가 목격 한 절망의 주를 절약 할 수 있기를 바랍니다.

// Instantiate a local raw phpiredis $client and execute get/set commands using $client directly 
// @Result: This WORKS :D 
$client = phpiredis_connect('127.0.0.1', 6379); 
$key = "table_name-_-$this->id"; 
foreach($args as $prop=>$val) 
    if(isset($prop) && isset($val)) 
     phpiredis_command($client, "hset $key $prop $val"); 
$obj = phpiredis_command($client, "hgetall $key"); 
echo json_encode($obj); 
phpiredis_disconnect($client); 
: 이것은 하나의 pthreads에서 phpiredis를 사용해야하는 방법입니다