6

LD_PRELOADメカニズムを使用してpthread_cond_broadcastへの呼び出しを挿入しようとしています。挿入されたpthread_cond_broadcast関数は、元のpthread_cond_broadcastを呼び出すだけです。ただし、pthread_cond_waitとpthread_cond_broadcastの両方が呼び出される非常に単純なpthreadコードの場合、glibcでセグメンテーション違反が発生するか(glibc 2.11.1の場合)、プログラムがハングします(glibc 2.15の場合)。その上で何か手がかりが起こっていますか?

介入コード(共有ライブラリとしてコンパイルされます):

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <dlfcn.h>

static int (*orig_pthread_cond_broadcast)(pthread_cond_t *cond) = NULL;

__attribute__((constructor))
static void start() {
    orig_pthread_cond_broadcast =
        (int (*)()) dlsym(RTLD_NEXT, "pthread_cond_broadcast");
    if (orig_pthread_cond_broadcast == NULL) {
        printf("pthread_cond_broadcast not found!!!\n");
        exit(1);
    }
}

__attribute__((__visibility__("default")))
int pthread_cond_broadcast(pthread_cond_t *cond) {
    return orig_pthread_cond_broadcast(cond);
}

単純なpthreadプログラム:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t cond_mutex;
pthread_cond_t cond_var;
int condition;

void *thread0_work(void *arg) {
    pthread_mutex_lock(&cond_mutex);
    printf("Signal\n");
    condition = 1;
    pthread_cond_broadcast(&cond_var);
    pthread_mutex_unlock(&cond_mutex);
    return NULL;
}

void *thread1_work(void *arg) {
    pthread_mutex_lock(&cond_mutex);
    while (condition == 0) {
        printf("Wait\n");
        pthread_cond_wait(&cond_var, &cond_mutex);
        printf("Done waiting\n");
    }
    pthread_mutex_unlock(&cond_mutex);
    return NULL;
}

int main() {
    pthread_t thread1;

    pthread_mutex_init(&cond_mutex, NULL);
    pthread_cond_init(&cond_var, NULL);

    pthread_create(&thread1, NULL, thread1_work, NULL);

    // Slowdown this thread, so the thread 1 does pthread_cond_wait.
    usleep(1000);

    thread0_work(NULL);

    pthread_join(thread1, NULL);

    return 0;
}

編集:

glibc 2.11.1の場合、gdbbtは次のようになります。

(gdb) set environment LD_PRELOAD=./libintercept.so
(gdb) run
Starting program: /home/seguljac/intercept/main 
[Thread debugging using libthread_db enabled]
[New Thread 0x7ffff7436700 (LWP 19165)]
Wait
Signal
Before pthread_cond_broadcast

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff79ca0e7 in pthread_cond_broadcast@@GLIBC_2.3.2 () from /lib/libpthread.so.0
(gdb) bt
#0  0x00007ffff79ca0e7 in pthread_cond_broadcast@@GLIBC_2.3.2 () from /lib/libpthread.so.0
#1  0x00007ffff7bdb769 in pthread_cond_broadcast () from ./libintercept.so
#2  0x00000000004008e8 in thread0_work ()
#3  0x00000000004009a4 in main ()

編集2:

(解決済み)R ..(ありがとう!)が提案したように、問題は、私のプラットフォームではpthread_cond_broadcastがバージョン管理されたシンボルであり、dlsymが間違ったバージョンを提供することです。このブログでは、この状況について詳しく説明しています:http: //blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions/

4

1 に答える 1

1

関数を介した呼び出しは、関数の別のバージョンで終了するようです。

With LD_PRELOAD:    __pthread_cond_broadcast_2_0 (cond=0x804a060) at old_pthread_cond_broadcast.c:37
Without LD_PRELOAD: pthread_cond_broadcast@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/pthread_cond_broadcast.S:39

したがって、状況はこの質問に似ています。つまり、互換性のないバージョンのpthread関数(シンボルのバージョン管理とdlsym)を取得しています。

このページは、少し複雑ですが、問題を解決する1つの方法を提供します:http://blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions/

于 2012-09-10T18:48:14.563 に答える