Phalcon初めてのおさわり




phalconを触ってみて詰まったときの調査メモてきな投稿です。


## まずはこんなコードを

認証を最初にして、その後データ処理というよくある？処理のを書いてみました。

```php:app.php
$app->before(function() use($app) {
	$headers = $app->request->getHeaders();
	$token = $headers['X_TOKEN'];
	// ごにょごにょ
});

$app->get('/', function () use ($app) {
    $transactionManager = $app->getDI()->getTransactionManager();
    $transaction = $transactionManager->get();
    $robot = new Robots();
    $robot->setTransaction($transaction);
    $robot->name = 'WALL·E';
    $robot->created_at = date('Y-m-d');
    if($robot->save()==false){
        $transaction->rollback("Can't save robot");
    }   
    $robotPart = new RobotParts();
    $robotPart->setTransaction($transaction);
    $robotPart->type = 'head';
    $robotPart->created_at = date('Y-m-d');
    if($robotPart->save()==false){
        $transaction->rollback("Can't save robot part");
    }   

    $transaction->commit();
    echo json_encode("abab");
});
```

```
 [error] 3176#0: *502 recv() failed (104: Connection reset by peer) while reading response header from upstream
```


早速エラーで動かない。
そして何がいけないのかエラー内容から判断がつかない。
ここから、苦境のはじまりです。。


## 何はともあれgoogle先生に

検索をしてみました。書いてあることは
Backtraceしてみろという情報
ハードルが高いしかし、情報が出てこないので
gdbしてみることに


## gdbしてみるよ

まずどうやってBacktraceするのかわからなかったので
またもや、google先生にお問い合わせすると

php-fpmで動かしている時は以下が参考になりました。

https://rtcamp.com/tutorials/php/core-dump-php5-fpm/
このサイトを参考に試してみる
service pgp5-fpm restart

↓
service php5-fpm restart
にして実行


```
 gdb /usr/sbin/php5-fpm /tmp/core-php5-fpm.17103
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/sbin/php5-fpm...Reading symbols from /usr/lib/debug//usr/sbin/php5-fpm...done.
done.
[New LWP 17103]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

warning: the debug information found in "/usr/lib/debug//usr/lib/php5/20121212/mysql.so" does not match "/usr/lib/php5/20121212/mysql.so" (CRC mismatch).


warning: the debug information found in "/usr/lib/debug/usr/lib/php5/20121212/mysql.so" does not match "/usr/lib/php5/20121212/mysql.so" (CRC mismatch).


warning: the debug information found in "/usr/lib/debug//usr/lib/php5/20121212/mysqli.so" does not match "/usr/lib/php5/20121212/mysqli.so" (CRC mismatch).


warning: the debug information found in "/usr/lib/debug/usr/lib/php5/20121212/mysqli.so" does not match "/usr/lib/php5/20121212/mysqli.so" (CRC mismatch).


warning: the debug information found in "/usr/lib/debug//usr/lib/php5/20121212/pdo_mysql.so" does not match "/usr/lib/php5/20121212/pdo_mysql.so" (CRC mismatch).


warning: the debug information found in "/usr/lib/debug/usr/lib/php5/20121212/pdo_mysql.so" does not match "/usr/lib/php5/20121212/pdo_mysql.so" (CRC mismatch).

Core was generated by `php-fpm: pool www                                                       '.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000000000070c7d9 in gc_zval_possible_root (zv=0x7f93e060dc00) at /build/buildd/php5-5.5.9+dfsg/Zend/zend_gc.c:143
143     /build/buildd/php5-5.5.9+dfsg/Zend/zend_gc.c: そのようなファイルやディレクトリはありません.
```

なにがなにやら・・
Segmentation faultといわれても何がいけないのかヒントをという内容。。




## どの記載がいけないのか調査

泥臭い感じでコメントデバッグ（自分命名）をして原因のphpコードをさぐってみる。

すると、
どうも
$headers = $app->request->getHeaders();
を記載してnewすると落ちるみたい。
$token = $app->request->getHeader('X_TOKEN');
とかくと落ちない。


## issuesにあがっていないかみてみる

ossなんだし他の人があげていないか調査してみる。

https://github.com/phalcon/cphalcon/issues?q=getHeaders+is%3Aissue+is%3Aopen+

issuesみてみたけどそれぽいのがあるようなないような。。
語学力ほしい。


## わからないならソースをみるしか

某探偵もこの世で解けないなぞなんてといっていたのでソースをみる。


getHeadersとgetHeaderをgrep
たぶんここ

```c:ext/http/request.c
/**
 * Returns the available headers in the request
 *
 * @return array
 */
PHP_METHOD(Phalcon_Http_Request, getHeaders){

    zval *_SERVER;
    HashPosition hp0; 
    zval **hd;

    array_init(return_value);
    _SERVER = phalcon_get_global(SS("_SERVER") TSRMLS_CC);
    if (unlikely(Z_TYPE_P(_SERVER) != IS_ARRAY)) {
        return;
    }    

    for (
        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(_SERVER), &hp0);
        zend_hash_get_current_data_ex(Z_ARRVAL_P(_SERVER), (void**)&hd, &hp0) == SUCCESS;
        zend_hash_move_forward_ex(Z_ARRVAL_P(_SERVER), &hp0)
    ) {  
        zval key = phalcon_get_current_key_w(Z_ARRVAL_P(_SERVER), &hp0);
    
        if (Z_TYPE(key) == IS_STRING && Z_STRLEN(key) > 5 && !memcmp(Z_STRVAL(key), "HTTP_", 5)) {
            zval *header;

            MAKE_STD_ZVAL(header);
            ZVAL_STRINGL(header, Z_STRVAL(key) + 5, Z_STRLEN(key) - 5, 1);
            phalcon_array_update_zval(&return_value, header, *hd, 0);
        }
    }
}
```

```c:ext/http/request.c
static PHP_METHOD(Phalcon_Http_Request, getHeader){

        zval *header, *_SERVER, *server_value, *key;

        phalcon_fetch_params(0, 1, 0, &header);

        _SERVER = phalcon_get_global(SS("_SERVER") TSRMLS_CC);
        if (phalcon_array_isset_fetch(&server_value, _SERVER, header)) {
                RETURN_ZVAL(server_value, 1, 0);
        }

        PHALCON_MM_GROW();
        PHALCON_INIT_VAR(key);
        PHALCON_CONCAT_SV(key, "HTTP_", header);
        if (phalcon_array_isset_fetch(&server_value, _SERVER, key)) {
                RETURN_CTOR(server_value);
        }

        RETURN_MM_EMPTY_STRING();
}
```

ソースみてもどうすればいいのか。。
あやしそうなのは、

```
        if (Z_TYPE(key) == IS_STRING && Z_STRLEN(key) > 5 && !memcmp(Z_STRVAL(key), "HTTP_", 5)) {
            zval *header;

            MAKE_STD_ZVAL(header);
            ZVAL_STRINGL(header, Z_STRVAL(key) + 5, Z_STRLEN(key) - 5, 1);
            phalcon_array_update_zval(&return_value, header, *hd, 0);
        }
```


## buildしてみる

phalconをインストールするときは64bitだと
build/64bits/phalcon.c
がメインみたいだけどデバッグするときはci参考にしたほうがと思い

 .travis.ymlを参考にbuildしてみる

```
cd ext
export CFLAGS="-g3 -O1 -std=gnu90 -Wall -Werror -Wno-error=uninitialized"
phpize
./configure --silent --enable-phalcon
make --silent -j4
sudo make --silent install
sudo service php5-fpm restart
```

ビルドできた


## 調査調査

またまたコメントでバッグ

phalcon_array_update_zval(&return_value, header, *hd, 0);
をコメントすると落ちなくなる。

phalcon_array_update_zvalが怪しい

ソースでphalcon_array_update_zvalを使っているところをみると
４つ目の引数が０をPH_COPYにしているのがちらほら
ext/kernel/main.hだとPH_COPYは1024らしい

```
        if (Z_TYPE(key) == IS_STRING && Z_STRLEN(key) > 5 && !memcmp(Z_STRVAL(key), "HTTP_", 5)) {
            zval *header;

            MAKE_STD_ZVAL(header);
            ZVAL_STRINGL(header, Z_STRVAL(key) + 5, Z_STRLEN(key) - 5, 1);
            phalcon_array_update_zval(&return_value, header, *hd, PH_COPY);
        }
```
にしてみてコンパイルしてみる

```
make clean
make --silent -j4
sudo make --silent install 
sudo service php5-fpm restart
```

落ちなくなったけどこれでいいのだろうか。。

build/64bits/phalcon.c
を生成？するにはどうするのかわかっていないです。



## 結論

phalconでつまったときのハードルが高くてつらい。。
2系phalconが救世主になることを願っています。


## 追加

ヒントもらったので早速調査
osがubuntueなで楽？してデバッグツールインストールできないみたい。
https://forums.ubuntulinux.jp/viewtopic.php?id=15386
をみると「thread apply all bt」してライブラリ名から調べるとある。


早速実行



```
(gdb) thread apply all bt

Thread 1 (Thread 0x7f93e07dd740 (LWP 17103)):
#0  0x000000000070c7d9 in gc_zval_possible_root (zv=0x7f93e060dc00) at /build/buildd/php5-5.5.9+dfsg/Zend/zend_gc.c:143
#1  0x00000000006fb118 in zend_hash_destroy (ht=0x7f93e060b6e8) at /build/buildd/php5-5.5.9+dfsg/Zend/zend_hash.c:560
#2  0x00000000006ec58b in _zval_dtor_func (zvalue=0x7f93e060b260) at /build/buildd/php5-5.5.9+dfsg/Zend/zend_variables.c:45
#3  0x00000000006dd660 in _zval_dtor (zvalue=0x7f93e060b260) at /build/buildd/php5-5.5.9+dfsg/Zend/zend_variables.h:35
#4  i_zval_ptr_dtor (zval_ptr=0x7f93e060b260) at /build/buildd/php5-5.5.9+dfsg/Zend/zend_execute.h:81
#5  _zval_ptr_dtor (zval_ptr=<optimized out>) at /build/buildd/php5-5.5.9+dfsg/Zend/zend_execute_API.c:426
#6  0x00000000006f9ad5 in zend_hash_apply_deleter (ht=ht@entry=0xcc9308 <executor_globals+360>, p=0x7f93e060e3f0) at /build/buildd/php5-5.5.9+dfsg/Zend/zend_hash.c:650
#7  0x00000000006fb2d8 in zend_hash_graceful_reverse_destroy (ht=0xcc9308 <executor_globals+360>) at /build/buildd/php5-5.5.9+dfsg/Zend/zend_hash.c:687
#8  0x00000000006ddd46 in shutdown_executor () at /build/buildd/php5-5.5.9+dfsg/Zend/zend_execute_API.c:247
#9  0x00000000006ed542 in zend_deactivate () at /build/buildd/php5-5.5.9+dfsg/Zend/zend.c:935
#10 0x000000000068d98d in php_request_shutdown (dummy=dummy@entry=0x0) at /build/buildd/php5-5.5.9+dfsg/main/main.c:1808
#11 0x0000000000463524 in main (argc=<optimized out>, argv=<optimized out>) at /build/buildd/php5-5.5.9+dfsg/sapi/fpm/fpm/fpm_main.c:1961
```

fromないから必要なpackageはいっていると判断していいのかな。。

この呪文みたいな文字をみていると寝むけが。。


ちなみに自前環境はconohaちゃんを使っています。
https://github.com/galigalikun/conoha-env