Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:36788 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 51521 invoked from network); 3 Apr 2008 23:35:38 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 3 Apr 2008 23:35:38 -0000 Authentication-Results: pb1.pair.com header.from=Kannan@facebook.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=Kannan@facebook.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain facebook.com designates 204.15.23.140 as permitted sender) X-PHP-List-Original-Sender: Kannan@facebook.com X-Host-Fingerprint: 204.15.23.140 fw-sf2p.facebook.com Received: from [204.15.23.140] ([204.15.23.140:54394] helo=mailout-sf2p.facebook.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 4B/1D-07453-9C965F74 for ; Thu, 03 Apr 2008 18:35:38 -0500 Received: from SF2PMXF01.TheFacebook.com (sf2pmxf01.thefacebook.com [192.168.16.11]) by pp01.sf2p.tfbnw.net (8.14.1/8.14.1) with ESMTP id m33NZY9D007678 for ; Thu, 3 Apr 2008 16:35:34 -0700 Received: from Sf2pmxb04.TheFacebook.com ([192.168.16.99]) by SF2PMXF01.TheFacebook.com with Microsoft SMTPSVC(6.0.3790.3959); Thu, 3 Apr 2008 16:34:28 -0700 X-MimeOLE: Produced By Microsoft Exchange V6.5 Content-class: urn:content-classes:message MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----_=_NextPart_001_01C895E3.42A8CDFB" Date: Thu, 3 Apr 2008 16:35:37 -0700 Message-ID: <2EE58C11758A3C4A929C8FFE3779827F32AE20@Sf2pmxb04.TheFacebook.com> X-MS-Has-Attach: X-MS-TNEF-Correlator: Thread-Topic: [PHP-DEV] memory corruptions in APC env when using references or extract(..., EXTR_REFS) [was re: references / zend_assign_to_variable / IS_CONST operands in APC] Thread-Index: AciRQX+P8i5UBPjLR5OvW0BrnHt10QEnvcaw To: X-OriginalArrivalTime: 03 Apr 2008 23:34:28.0903 (UTC) FILETIME=[42B06370:01C895E3] X-Proofpoint-Virus-Version: vendor=fsecure engine=1.12.7113:2.4.4,1.2.40,4.0.166 definitions=2008-04-03_05:2008-04-02,2008-04-03,2008-04-03 signatures=0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 ipscore=0 phishscore=0 bulkscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx engine=5.0.0-0803050000 definitions=main-0804030190 Subject: FW: [PHP-DEV] memory corruptions in APC env when using references or extract(..., EXTR_REFS) [was re: references / zend_assign_to_variable / IS_CONST operands in APC] From: Kannan@facebook.com ("Kannan Muthukkaruppan") ------_=_NextPart_001_01C895E3.42A8CDFB Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Resending the mail since I didn't get any responses. To add: This seems to be a fundamental issue with running PHP in an environment that keeps op arrays in shared memory (such as APC) and using "references" or other reference semantic features of PHP (such as extract with the EXTR_REFS option). Temporarily, we are working around it by setting tweaking zend_opcode.c:pass_two(). Recall that pass_two() sets is_ref to 1 and refcount to 2 for all IS_CONST operands in the op arrays. Existing code from zend_opcode.c:pass_two(): if (opline->op1.op_type =3D=3D IS_CONST) { opline->op1.u.constant.is_ref =3D 1; opline->op1.u.constant.refcount =3D 2; /* Make sure is_ref won't be reset */ } if (opline->op2.op_type =3D=3D IS_CONST) { opline->op2.u.constant.is_ref =3D 1; opline->op2.u.constant.refcount =3D 2; } To minimize the chance of race condition I describe in the earlier mail, we are setting refcount in both cases above to a much larger value (~100M) instead of 2; and have stopped seeing problems now. But this is a workaround at best. Would like feedback on whether my analysis is correct in the first place, and are if there any thoughts on a better fix. regards, Kannan -----Original Message----- From: Kannan Muthukkaruppan [mailto:Kannan@facebook.com]=20 Sent: Friday, March 28, 2008 7:06 PM To: internals@lists.php.net Subject: [PHP-DEV] references / zend_assign_to_variable / IS_CONST operands in APC Consider the following small test case where $y is first made to be a reference to $x. And next, we assign a literal to $y. =20 Example #1: refcount; zval garbage; =20 if (type!=3DIS_TMP_VAR) { value->refcount++; <----- incrementing the refcount of RHS zval } garbage =3D *variable_ptr; *variable_ptr =3D *value; variable_ptr->refcount =3D refcount; variable_ptr->is_ref =3D 1; if (type!=3DIS_TMP_VAR) { zendi_zval_copy_ctor(*variable_ptr); value->refcount--; <------ and then decrementing it back... } zendi_zval_dtor(garbage); } } =20 I am trying to understand the rationale for value->refcount++ and value->refcount-- above. Why do we need that? =20 With PHP running in apache+APC environment, the "null" literal is an IS_CONST operand in the op_array in APC (shared memory). And incrementing/decrementing a ref count on the shared memory area without a mutex can cause unexpected problems due to race conditions (and eventually lead to memory corruptions etc.) =20 Recall that zend_opcode.c:pass_two() sets "is_ref" on all IS_CONST operands to 1, as a way to allow op_arrays to be sharable across processes. And indeed, in the simpler case of an assignment such as in the following example (#2), zend_assign_to_variable() notices that the RHS has "is_ref" set and goes on to make a copy (rather than incrementing the RHS's refcount). =20 Example #2: =20