Re: IS_INTERNED for apc + zend mixtures

[email protected] (Dmitry Stogov) Thu, 28 Jul 2011 11:48:50 +0400
Newsgroups php.apc.dev
Message-ID <[email protected]>
Hi Gopal,

We already support interned strings in Zend opcode cache (O+) without 
problems.  I don't remember all the details but I'll try to explain how 
it works.

O+ uses single SHM memory block to keep all the interned strings.

It overrides CG(interned_strings_start) and CG(interned_strings_end) 
with SHM memory block boundaries. It also overrides 
zend_new_interned_string, zend_interned_strings_snapshot and 
zend_interned_strings_restore with dummy functions so PHP doesn't create 
interned strings itself. O+ stores interned strings itself when copies 
compiled script into SHM.

on MINIT it also copies names of internal entities (functions, classes, 
properties, methods, constants and auto globals) into the same SHM block.

I see that I did something similar for APC too. The difference may be in 
shutdown sequence.

Thanks. Dmitry.

On 07/28/2011 12:12 AM, Gopal V wrote:
> Hi,
>
> I'm trying to fix apc for php 5.4 and the primary issue seems to be
> the actual check inside IS_INTERNED.
>
> #define IS_INTERNED(s) \
> (((s) >= CG(interned_strings_start)) && ((s) < CG(interned_strings_end)))
>
> Except when apc does implement interned strings, there are two
> blocks which qualify to be interned. The one that zend maintains
> in the original CG which allocates things like the "stdClass"
> string.
>
> So I end up with a double free error on this
>
> ==32196== Invalid free() / delete / delete[]
> ==32196== at 0x4C270BD: free (vg_replace_malloc.c:366)
> ==32196== by 0x68FA14: destroy_zend_class (zend_opcode.c:331)
> ==32196== by 0x6A52B2: zend_hash_clean (zend_hash.c:596)
> ==32196== by 0x705F6FF: apc_interned_strings_shutdown (apc_string.c:226)
> ==32196== by 0x70579A9: apc_module_shutdown (apc_main.c:895)
> ==32196== by 0x704E02E: zm_shutdown_apc (php_apc.c:373)
> ==32196== by 0x69E0A4: module_destructor (zend_API.c:2248)
> ==32196== by 0x6A4CC6: zend_hash_apply_deleter (zend_hash.c:650)
> ==32196== by 0x6A4F67: zend_hash_graceful_reverse_destroy (zend_hash.c:687)
> ==32196== by 0x6989F2: zend_shutdown (zend.c:806)
> ==32196== by 0x63C48C: php_module_shutdown (main.c:2264)
> ==32196== by 0x742824: main (php_cli.c:1371)
> ==32196== Address 0x6c58a68 is 84,600 bytes inside a block of size
> 1,048,576 alloc'd
> ==32196== at 0x4C274A8: malloc (vg_replace_malloc.c:236)
> ==32196== by 0x6B888C: zend_interned_strings_init (zend_string.c:48)
> ==32196== by 0x699A65: zend_startup (zend.c:740)
> ==32196== by 0x63D9F4: php_module_startup (main.c:1936)
> ==32196== by 0x740C7C: php_cli_startup (php_cli.c:414)
> ==32196== by 0x7425C8: main (php_cli.c:1336)
>
> We probably need an override for that so that we can nest multiple
> interned blocks which are non contiguous between different modules.
>
> Cheers,
> Gopal