Skip to content

Commit

Permalink
[Debug] Add symfony_debug_backtrace() that works with fatal errors
Browse files Browse the repository at this point in the history
  • Loading branch information
Julien Pauli authored and nicolas-grekas committed Apr 3, 2015
1 parent 8be2903 commit eacdc62
Show file tree
Hide file tree
Showing 7 changed files with 329 additions and 93 deletions.
133 changes: 133 additions & 0 deletions src/Symfony/Component/Debug/Resources/ext/README.md
@@ -0,0 +1,133 @@
Symfony Debug Extension
=======================

This extension publishes several functions to help building powerful debugging tools.

symfony_zval_info()
-------------------

- exposes zval_hash/refcounts, allowing e.g. efficient exploration of arbitrary structures in PHP,
- does work with references, preventing memory copying.

Its behavior is about the same as:

```php
<?php

function symfony_zval_info($key, $array, $options = 0)
{

// $options is currently not used, but could be in future version.

if (!array_key_exists($key, $array)) {
return null;
}

$info = array(
'type' => gettype($array[$key]),
'zval_hash' => /* hashed memory address of $array[$key] */,
'zval_refcount' => /* internal zval refcount of $array[$key] */,
'zval_isref' => /* is_ref status of $array[$key] */,
);

switch ($info['type']) {
case 'object':
$info += array(
'object_class' => get_class($array[$key]),
'object_refcount' => /* internal object refcount of $array[$key] */,
'object_hash' => spl_object_hash($array[$key]),
'object_handle' => /* internal object handle $array[$key] */,
);
break;

case 'resource':
$info += array(
'resource_handle' => (int) $array[$key],
'resource_type' => get_resource_type($array[$key]),
'resource_refcount' => /* internal resource refcount of $array[$key] */,
);
break;

case 'array':
$info += array(
'array_count' => count($array[$key]),
);
break;

case 'string':
$info += array(
'strlen' => strlen($array[$key]),
);
break;
}

return $info;
}
```

symfony_debug_backtrace()
-------------------------

This function works like debug_backtrace(), except that it can fetch the full backtrace in case of fatal errors:

```php
function foo() { fatal(); }
function bar() { foo(); }

function sd() { var_dump(symfony_debug_backtrace()); }

register_shutdown_function('sd');

bar();

/* Will output
Fatal error: Call to undefined function fatal() in foo.php on line 42
array(3) {
[0]=>
array(2) {
["function"]=>
string(2) "sd"
["args"]=>
array(0) {
}
}
[1]=>
array(4) {
["file"]=>
string(7) "foo.php"
["line"]=>
int(1)
["function"]=>
string(3) "foo"
["args"]=>
array(0) {
}
}
[2]=>
array(4) {
["file"]=>
string(102) "foo.php"
["line"]=>
int(2)
["function"]=>
string(3) "bar"
["args"]=>
array(0) {
}
}
}
*/
```

Usage
-----

The extension is compatible with ZTS mode, and should be supported by PHP5.3, 5.4, 5.5 and 5.6.
To enable the extension from source, run:

```
phpize
./configure
make
sudo make install
```
72 changes: 0 additions & 72 deletions src/Symfony/Component/Debug/Resources/ext/README.rst

This file was deleted.

13 changes: 9 additions & 4 deletions src/Symfony/Component/Debug/Resources/ext/php_symfony_debug.h
Expand Up @@ -13,7 +13,7 @@
extern zend_module_entry symfony_debug_module_entry;
#define phpext_symfony_debug_ptr &symfony_debug_module_entry

#define PHP_SYMFONY_DEBUG_VERSION "1.0"
#define PHP_SYMFONY_DEBUG_VERSION "2.7"

#ifdef PHP_WIN32
# define PHP_SYMFONY_DEBUG_API __declspec(dllexport)
Expand All @@ -29,6 +29,8 @@ extern zend_module_entry symfony_debug_module_entry;

ZEND_BEGIN_MODULE_GLOBALS(symfony_debug)
intptr_t req_rand_init;
void (*old_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
zval *debug_bt;
ZEND_END_MODULE_GLOBALS(symfony_debug)

PHP_MINIT_FUNCTION(symfony_debug);
Expand All @@ -40,11 +42,14 @@ PHP_GINIT_FUNCTION(symfony_debug);
PHP_GSHUTDOWN_FUNCTION(symfony_debug);

PHP_FUNCTION(symfony_zval_info);
PHP_FUNCTION(symfony_debug_backtrace);

static char *_symfony_debug_memory_address_hash(void *);
static char *_symfony_debug_memory_address_hash(void * TSRMLS_DC);
static const char *_symfony_debug_zval_type(zval *);
static const char* _symfony_debug_get_resource_type(long);
static int _symfony_debug_get_resource_refcount(long);
static const char* _symfony_debug_get_resource_type(long TSRMLS_DC);
static int _symfony_debug_get_resource_refcount(long TSRMLS_DC);

void symfony_debug_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);

#ifdef ZTS
#define SYMFONY_DEBUG_G(v) TSRMG(symfony_debug_globals_id, zend_symfony_debug_globals *, v)
Expand Down

0 comments on commit eacdc62

Please sign in to comment.