2017-01-31 16 views
3

私は、別のスレッドで値を生成し、データが準備できたらコールバック関数を実行する、単純なkdb +共有ライブラリを作成しています。アプリケーションは、新しいスレッドのファイル記述子にデータを書き込み、メインのイベントループでこれを読み込みます。ミューテックスをロックおよびロック解除しようとすると、アプリケーションがsegfaultingしているように見えます。セグメンテーションフォルト - pthread mutexロック問題

ループに小さな睡眠を導入すると、セグメンテーションが消えているようです。これは、pthread_mutex_lock呼び出しが、期待通りにロックが取得されるまでスレッドをブロックしていないことを示唆しています。

#include <k.h> 
#include <pthread.h> 
#include <time.h> 

#define PIPE_CAPACITY 65536 

static int fd; 
static pthread_t thread; 
static pthread_mutex_t lock; 

K callback(int d) 
{ 
    K data; 

    // Aquire mutex lock and read from fd 
    pthread_mutex_lock(&lock); 
    read(d, &data, PIPE_CAPACITY); 
    pthread_mutex_unlock(&lock); 

    // kdb+ callback 
    k(0, (char *)"callback", r1(data), (K)0); 

    return (K)0; 
} 

void* loop() 
{ 
    while (1) { 
     struct timespec ts; 
     struct tm *time; 

     // Get seconds and nanoseconds since epoch 
     clock_gettime(CLOCK_REALTIME, &ts); 

     // Adjust for kdb+ 
     time = gmtime(&ts.tv_sec); 
     time->tm_sec = 0; 
     time->tm_min = 0; 
     time->tm_hour = 0; 
     ts.tv_sec -= mktime(time); // Subtract seconds between epoch and midnight 

     // Create kdb+ timestamp 
     K data = ktj(-KN, ts.tv_sec * 1000000000 + ts.tv_nsec); 

     // Aquire mutex lock and write to fd 
     pthread_mutex_lock(&lock); 
     write(fd, &data, sizeof(K)); 
     pthread_mutex_unlock(&lock); 
    } 
} 

K init() 
{ 
    // Initialize mutex 
    pthread_mutex_init(&lock, NULL); 

    // Create file descriptor 
    fd = eventfd(0, 0); 

    // Register callback 
    sd1(fd, callback); 

    // Launch thread 
    pthread_create(&thread, NULL, loop, NULL); 
} 
+0

関連はありませんが、実際には 'K 'のような1文字の型名は避けてください。 –

+0

「メイン」機能を提供できますか?スレッドの作成前に初期化が有効になるかどうか – Emisilve86

+0

@MichaelWalzこれは私の個人的な選択ではなく、私が使用しなければならないAPIになります。[kh](http://code.kx.com/wsvn/code/kx/kdb%2B/c/c/ kh) –

答えて

3

KとしてKHで定義されたポインタ型であることを思い出してください:

typedef struct k0{..}*K; 

これは、あなたが主に実行するコールバックに「ループ」スレッドで作成されたオブジェクトへのポインタを送信する手段と糸。これはkdb +がスレッドごとに別個のメモリプルを使用するため動作しません。代わりにデータのコピーを渡すことをお勧めします。

もう一つの問題は、あなたが65536のバイトを読んでいるライン

read(d, &data, PIPE_CAPACITY); 

であるが、宛先として8バイトの変数のアドレスを渡します。遅延を導入するときにsegfaultを取得しない理由は、この場合、ループは読み込み間に8バイト以上を書き込む機会を得られないからです。

最後に、eventfdによって返されたファイルディスクリプタを読み取り/書き込みバッファとして使用できるかどうかは確かではありません。私は良い古いpipe()呼び出しを使用することをお勧めします。

あなたのコードの次のような変形が私の作品:

#include <k.h> 
#include <pthread.h> 
#include <time.h> 
#include <unistd.h> 

static int fd[2]; 
static pthread_t thread; 
static pthread_mutex_t lock; 

K callback(int d) 
{ 
    K data = ktj(-KN, 0); 

    // Aquire mutex lock and read from fd 
    pthread_mutex_lock(&lock); 
    read(d, (void *)&data->j, sizeof(data->j)); 
    pthread_mutex_unlock(&lock); 

    // kdb+ callback 
    k(0, (char *)"callback", data, (K)0); 

    return (K)0; 
} 

void* loop() 
{ 
    while (1) { 
     struct timespec ts; 
     struct tm *time; 

     // Get seconds and nanoseconds since epoch 
     clock_gettime(CLOCK_REALTIME, &ts); 

     // Adjust for kdb+ 
     time = gmtime(&ts.tv_sec); 
     time->tm_sec = 0; 
     time->tm_min = 0; 
     time->tm_hour = 0; 
     ts.tv_sec -= mktime(time); // Subtract seconds between epoch and midnight 

     // Create kdb+ timestamp 
     J data = (J)ts.tv_sec * 1000000000 + ts.tv_nsec; 

     // Aquire mutex lock and write to fd 
     pthread_mutex_lock(&lock); 
     write(fd[1], &data, sizeof(data)); 
     pthread_mutex_unlock(&lock); 
    } 
} 

K1(init) 
{ 
    // Initialize mutex 
    pthread_mutex_init(&lock, NULL); 

    // Create file descriptor 
    pipe(fd); 

    // Register callback 
    sd1(fd[0], callback); 

    // Launch thread 
    pthread_create(&thread, NULL, loop, NULL); 

    R ktj(0, 0); 
} 

、テストXCで上記のコードをコピーし、

$ gcc -Wall -shared -fPIC -I $(pwd) -DKXVER=3 x.c -o x.so 

をコンパイルし、次のqのコードを実行するには:

callback:0N! 
init:`:./x 2:(`init;1) 
init[] 
関連する問題