2017-01-31 58 views
3

我正在創建一個簡單的kdb +共享庫,它在單獨的線程上生成值,並在數據準備就緒時執行回調函數。應用程序正在將數據寫入新線程中的文件描述符並在主事件循環中從中讀取。嘗試鎖定和解鎖互斥鎖時,該應用程序似乎是暫時性的。分段錯誤 - pthread互斥鎖定問題

如果我在循環中引入小睡眠,segfault似乎消失。這將暗示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'。 –

+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字節的變量作爲目標的地址。當你引入延遲時,你沒有得到段錯誤的原因是,在這種情況下,循環沒有機會在讀取之間寫入超過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[]