問題
erlang を起動するpthread/ethr_event.c:98: Fatal error in wait__(): Function not implemented (38)と、最近のディストリビューションでは、FUTEX_WAIT_PRIVATE および FUTEX_WAKE_PRIVATE を実装していないカーネルと対話するプリコンパイル済み Erlang バイナリの結果である可能性が最も高いメッセージです。Amazon が EC2 用に提供するカーネルは、これらの FUTEX_PRIVATE_ マクロを実装していません。
ディストリビューションが他のパッケージの要件としてカーネル ヘッダーを /usr/include/linux にインストールする場合、ec2 ボックスでソースから Erlang をビルドしようとすると、同じように失敗する可能性があります。(たとえば、Centos では、gcc、gcc-c++、glibc-devel、glibc-headers などの前提条件として kernel-headers パッケージが必要です)。パッケージによってインストールされたヘッダーが EC2 イメージ作成スクリプトによってインストールされたカーネルと一致しないため、Erlang は FUTEX_WAIT_PRIVATE と FUTEX_WAKE_PRIVATE が利用可能であると誤って想定します。
修正
erts/include/internal/pthread/ethr_event.hこれを修正するには、 _PRIVATE 以外の futex 実装を使用するよう
に手動でパッチを適用するのが最速です。
#if defined(FUTEX_WAIT_PRIVATE) && defined(FUTEX_WAKE_PRIVATE)
# define ETHR_FUTEX_WAIT__ FUTEX_WAIT_PRIVATE
# define ETHR_FUTEX_WAKE__ FUTEX_WAKE_PRIVATE
#else
# define ETHR_FUTEX_WAIT__ FUTEX_WAIT
# define ETHR_FUTEX_WAKE__ FUTEX_WAKE
#endif
なるべき
//#if defined(FUTEX_WAIT_PRIVATE) && defined(FUTEX_WAKE_PRIVATE)
//# define ETHR_FUTEX_WAIT__ FUTEX_WAIT_PRIVATE
//# define ETHR_FUTEX_WAKE__ FUTEX_WAKE_PRIVATE
//#else
# define ETHR_FUTEX_WAIT__ FUTEX_WAIT
# define ETHR_FUTEX_WAKE__ FUTEX_WAKE
//#endif
クイックテスト
private futex の問題が問題であると思われるが、Erlang をすべて再コンパイルする前に確認したい場合は、次のプログラムで問題を突き止めることができます。
#include <sys/syscall.h>
#include <unistd.h>
#include <sys/time.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
typedef uint32_t u32; /* required on older kernel headers to fix a bug in futex.h Delete this line if it causes problems. */
#include <linux/futex.h>
int main(int argc, char *argv[])
{
#if defined(FUTEX_WAIT) && defined(FUTEX_WAKE)
uint32_t i = 1;
int res = 0;
res = syscall(__NR_futex, (void *) &i, FUTEX_WAKE, 1,
(void*)0,(void*)0, 0);
if (res != 0)
{
printf("FUTEX_WAKE HAD ERR %i: %s\n", errno, strerror(errno));
} else {
printf("FUTEX_WAKE SUCCESS\n");
}
res = syscall(__NR_futex, (void *) &i, FUTEX_WAIT, 0,
(void*)0,(void*)0, 0);
if (res != 0)
{
printf("FUTEX_WAIT HAD ERR %i: %s\n", errno, strerror(errno));
} else {
printf("FUTEX_WAIT SUCCESS\n");
}
#else
printf("FUTEX_WAKE and FUTEX_WAIT are not defined.\n");
#endif
#if defined(FUTEX_WAIT_PRIVATE) && defined(FUTEX_WAKE_PRIVATE)
uint32_t j = 1;
int res_priv = 0;
res_priv = syscall(__NR_futex, (void *) &j, FUTEX_WAKE_PRIVATE, 1,
(void*)0,(void*)0, 0);
if (res_priv != 0)
{
printf("FUTEX_WAKE_PRIVATE HAD ERR %i: %s\n", errno, strerror(errno));
} else {
printf("FUTEX_WAKE_PRIVATE SUCCESS\n");
}
res_priv = syscall(__NR_futex, (void *) &j, FUTEX_WAIT_PRIVATE, 0,
(void*)0,(void*)0, 0);
if (res_priv != 0)
{
printf("FUTEX_WAIT_PRIVATE HAD ERR %i: %s\n", errno, strerror(errno));
} else {
printf("FUTEX_WAIT_PRIVATE SUCCESS\n");
}
#else
printf("FUTEX_WAKE_PRIVATE and FUTEX_WAIT_PRIVATE are not defined.\n");
#endif
return 0;
}
に貼り付けfutextest.cます。gcc futextest.c./a.out
カーネルがプライベート futex を実装している場合は、
FUTEX_WAKE SUCCESS
FUTEX_WAIT SUCCESS
FUTEX_WAKE_PRIVATE SUCCESS
FUTEX_WAIT_PRIVATE SUCCESS
_PRIVATE futex 関数のないカーネルがある場合、次のように表示されます。
FUTEX_WAKE SUCCESS
FUTEX WAIT SUCCESS
FUTEX_WAKE_PRIVATE HAD ERR 38: Function not implemented
FUTEX_WAIT_PRIVATE HAD ERR 38: Function not implemented
この修正により、Erlang がコンパイルできるようになり、ここで説明されている --nodeps メソッドを使用して rabbitmq をインストールできる環境が生成されます。