絖綛 N@i.jp  昨日:00015961
 今日:00003278
 総計:00156054
keywords
管理者専用
  Post   Add link   Control Panel 































新しいトピック
最新:11/14 16:41


新しいコメント
最新:07/28 16:47






管理人へMAIL

プライバシーポリシー

次は PHP 8.1 へ(2)

テスト全滅 orz


4. テスト全滅対応

 これまでの修正でビルド(configure, make)を突破できたので、make test で動作チェックを行なわせたところ、

Fatal Error Unable to allocate shared memory segment of 134217728 bytes: shm_open: Invalid argument (22)

とのエラーメッセージが出て全テスト項目が失敗してしまいました。どうやら shm_open() でエラー(22:EINVAL)が起きて共有メモリの確保ができないと言っているようですね。
 どんな状態で shm_open() が呼び出されているのか gdb で追いかけてみたところ、

$ cd tests/run-test
$ ./test001.sh gdb
GNU gdb 6.3.50-20050815 (Apple version gdb-573) (Fri Oct 20 15:54:33 GMT 2006)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "powerpc-apple-darwin"...Reading symbols for shared libraries .................... done

(gdb) b shm_open
Breakpoint 1 at 0x9001b7c4
(gdb) r
Starting program: /home/hoge/php-8.1.15/sapi/cli/php -n -c /home/hoge/php-8.1.15/tmp-php.ini 〜 -d memory_limit=128M 〜 -f /home/hoge/php-8.1.15/tests/run-test/test001.php
Reading symbols for shared libraries .++....+++.+.++++.++..+.........+...........++ done
Reading symbols for shared libraries . done
Reading symbols for shared libraries . done

Breakpoint 1, 0x9001b7c4 in shm_open ()
(gdb) info reg
r0             0x2698740    40470336
r1             0xbfffcc30   3221212208
r2             0xd2 210
r3             0xbfffccc8   3221212360  ←第一引数
r4             0x602    1538            ←第二引数(O_RDWR|O_CREAT|O_TRUNC)
r5             0x180    384             ←第三引数(0600)
r6             0x38 56
r7             0x64416363   1682006883
r8             0x656c6572   1701602674
r9             0x208    520
r10            0x5  5
r11            0x24000222   603980322
r12            0x9001b7a0   2416031648
r13            0x0  0
r14            0x0  0
r15            0xf  15
r16            0x3102f8f    51392399
r17            0x32b    811
r18            0x22 34
r19            0xd26a6c 13789804
r20            0xbfffcde0   3221212640
r21            0x269cf88    40488840
r22            0x8000000    134217728
r23            0x269c728    40486696
r24            0xbfffcdb8   3221212600
r25            0x0  0
r26            0x180    384
r27            0x602    1538
r28            0xbfffccc8   3221212360
r29            0xbfffccc8   3221212360
r30            0x31fa3c0    52405184
r31            0x9001b7a8   2416031656
pc             0x9001b7c4   2416031684
ps             0x2f030  192560
cr             0x82000222   2181038626
lr             0x9001b7a8   2416031656
ctr            0x9001b7a0   2416031648
xer            0x4  4
mq             0x0  0
fpscr          0x82024000   2181185536
vscr           0x10000  65536
vrsave         0x0  0
(gdb) x/s 0xbfffccc8
0xbfffccc8:  "/ZendAccelerator.16228"  ←第一引数で渡された共有メモリオブジェクト
(gdb) bt
#0  0x9001b7c4 in shm_open ()
#1  0x02698740 in create_segments ()
#2  0x026963c8 in zend_shared_alloc_try ()
#3  0x02696b9c in zend_shared_alloc_startup ()
#4  0x0267f954 in accel_post_startup ()
#5  0x0038c024 in zend_post_startup ()
#6  0x00317184 in php_module_startup ()
#7  0x0049ad54 in php_cli_startup ()
#8  0x00d36cc4 in main ()
(gdb) c
Continuing.
Sun Feb 12 05:32:55 2023 (2684415368): Fatal Error Unable to allocate shared memory segment of 134217728 bytes: shm_open: Invalid argument (22)

Program exited with code 0376.

 当該ソースは "ext/opcache/shared_alloc_posix.c" 内の以下の場所です。

static int create_segments(size_t requested_size, zend_shared_segment_posix ***shared_segments_p, int *shared_segments_count, char **error_in)
{
    zend_shared_segment_posix *shared_segment;
    char shared_segment_name[sizeof("/ZendAccelerator.") + 20];

    *shared_segments_count = 1;
    *shared_segments_p = (zend_shared_segment_posix **) calloc(1, sizeof(zend_shared_segment_posix) + sizeof(void *));
    if (!*shared_segments_p) {
        *error_in = "calloc";
        return ALLOC_FAILURE;
    }
    shared_segment = (zend_shared_segment_posix *)((char *)(*shared_segments_p) + sizeof(void *));
    (*shared_segments_p)[0] = shared_segment;

    sprintf(shared_segment_name, "/ZendAccelerator.%d", getpid());
    shared_segment->shm_fd = shm_open(shared_segment_name, O_RDWR|O_CREAT|O_TRUNC, 0600);
    if (shared_segment->shm_fd == -1) {
        *error_in = "shm_open";
        return ALLOC_FAILURE;
    }

    if (ftruncate(shared_segment->shm_fd, requested_size) != 0) {
        *error_in = "ftruncate";
        shm_unlink(shared_segment_name);
        return ALLOC_FAILURE;
    }

    shared_segment->common.p = mmap(0, requested_size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_segment->shm_fd, 0);
    if (shared_segment->common.p == MAP_FAILED) {
        *error_in = "mmap";
        shm_unlink(shared_segment_name);
        return ALLOC_FAILURE;
    }
    shm_unlink(shared_segment_name);

    shared_segment->common.pos = 0;
    shared_segment->common.size = requested_size;

    return ALLOC_SUCCESS;
}

 上記の shm_open()EINVAL(22) が発生していると言うことになります。EINVAL(Invalid argument) なので shm_open() に無効(Invalid)な引数が指定されたのであり、第一引数に指定した共有メモリオブジェクトの名前が不正である事が原因と考えられるのだけど、見たところ特に問題ないように思えます。もちろん第二引数、第三引数にも正しい値が渡されて来ていますね。
 これで行き詰まってしまい、数日間う〜んと唸ってばかりでした。何かがおかしい、何かを見落としているのか?ある時、ふと実機(Mac mini G4)で man shm_open を見たところ、こんな事が書いてあることに気付いたのです。

NAME
     shm_open -- open a shared memory object

SYNOPSIS
     #include 

     int
     shm_open(const char *name, int flags, mode_t mode);

ERRORS
     The named object is opened unless:

     [EINVAL]           The shm_open() operation is not supported.

ウチの Mac OS X では EINVAL は shm_open() がサポートされていないという意味だと?これじゃどうやってもダメじゃないか。では、何故このサポートされていない shm_open() で共有メモリを確保しようとするようになったのでしょうか?以前の PHP ではこのエラーは起きてないが、共有メモリは使っているはずです。
 色々とソースを眺めていたところ、"ext/opcache/zend_shared_alloc.c" の中に以下のテーブルがあるのを見つけました。

static const zend_shared_memory_handler_entry handler_table[] = {
#ifdef USE_MMAP
    { "mmap", &zend_alloc_mmap_handlers },
#endif
#ifdef USE_SHM
    { "shm", &zend_alloc_shm_handlers },
#endif
#ifdef USE_SHM_OPEN
    { "posix", &zend_alloc_posix_handlers },
#endif
#ifdef ZEND_WIN32
    { "win32", &zend_alloc_win32_handlers },
#endif
    { NULL, NULL}
};

共有メモリ獲得エントリのハンドラテーブルです。このテーブルを上から順に読んで共有メモリ獲得処理を呼び出し、共有メモリ獲得が成功すればそこで獲得処理終了。失敗したら次の共有メモリ獲得処理を呼び出すという仕組みらしいですな。ウチの Mac mini G4 では USE_MMAPUSE_SHM_OPEN の2つが有効になっているはずなので、

  1. zend_alloc_mmap_handlers "ext/opcache/shared_alloc_mmap.c" "create_segments()"mmap()
  2. zend_alloc_posix_handlers"ext/opcache/shared_alloc_posix.c""create_segments()"shm_open()

という呼び出し経路で共有メモリ獲得が試されます。そして、その何れもが失敗していることになります。
 調べたところ、以前の PHPでは最初の mmapルートで共有メモリ獲得が成功しているので、shm_openルートには行かないのだと言う事が分かりました。では、何故 PHP 8.1では mmap() が失敗するようになったのでしょう?

 そこで "shared_alloc_mmap.c" の以前のソースとの差分を調べてみたら、

$ diff ./shared_alloc_mmap.c /home/hoge/php-8.0.27/ext/opcache/shared_alloc_mmap.c
32,35d31
< #ifdef __APPLE__
< #include <mach/vm_statistics.h>
< #endif
<
46c42
<   int flags = PROT_READ | PROT_WRITE, fd = -1;
---
>   int flags = PROT_READ | PROT_WRITE;
49,53c45
<   flags |= PROT_MPROTECT(PROT_EXEC);
< #endif
< #ifdef VM_MAKE_TAG
<   /* allows tracking segments via tools such as vmmap */
<   fd = VM_MAKE_TAG(251U);
---
〜以下略〜

何のことはない、PHP 7.4で "Zend/zend_alloc.c" に行ったのと同じ事を、PHP 8.1 のタイミングで "ext/opcache/shared_alloc_mmap.c"にも行ったという事のようです。mmap() の第5引数(ファイルディスクリプタ)に特別な値を指定することで特殊なメモリページ上に共有メモリを獲得できるっぽいのだけど、ウチの Mac OS X でこれをやられると mmap() が失敗してしまいます。単にメモリ領域を獲得したいだけなので、ファイルディスクリプタには -1 を指定するようにようにすれば良い筈。そのためには、

//#ifdef __APPLE__
//#include <mach/vm_statistics.h>
//#endif

32行目からの3行を上のようにコメントアウトしてしまえば良いですね。この修正によって正常に共有メモリが獲得できるようになり、テスト項目が全滅なんて事はなくなりました。
 とは言うものの、テストが100%成功などと言うことにはならず、いくつかのテスト項目は失敗(FAIL)しています。案の定 fiber機能はほぼダメ。他にもいくつか失敗(FAIL)していますが、使わない機能ならどうってことないよね。ウチの Blogが使っている機能さえ動きゃ良いという強い(?)気持ちで行くしかないですね。

[続く]


■ このトピックへのコメント投稿フォーム ■
キャンセル
※ HTMLタグは使えません
* 名前
* MAIL
* URL
本文
PASS ※ 半角英数8文字まで
認証 ※ 七参六六参を半角数字で入力して下さい
  * 印の項目をcookieに保存する

2023 calendar
2月
1234
567891011
12131415161718
19202122232425
262728


掲示板
最新:08/15 17:19


GsBlog was developed by GUSTAV, Copyright(C) 2003, Web Application Factory All Rights Reserved.