2017-02-02 9 views
-1

Я пытается реализовать потоки в C на Linux (с клоном(), очевидно), но у меня возникла странная проблема.Linux Clone «убивает» главную тему

Во-первых, здесь мои функции мьютекса:

void mutex_lock(int* lock) { 
    while (!__sync_bool_compare_and_swap(lock, 0, 1)) { 
    syscall(SYS_futex, lock, FUTEX_WAIT_PRIVATE, 1, NULL, NULL, 0); 
    } 
} 

void mutex_unlock(int* lock) { 
    if (__sync_bool_compare_and_swap(lock, 1, 0)) { 
    syscall(SYS_futex, lock, FUTEX_WAKE_PRIVATE, 0, NULL, NULL, 0); 
    } 
} 

И моя структура Thread

typedef int (*ThreadCallback)(void*); 

typedef struct Thread { 

    void* alloc; 

    char lockSpace[sizeof(int) * 2]; /* Used to align lock pointer properly */ 
    int* lock; 
    int started; 
    int tid; 

    void* stack; 
    size_t stackSize; 

    ThreadCallback fn; 
    void* args; 

}* Thread; 

В моем коде, я выделяю и инициализировать-структуру темы я буду использовать позже

void* start = memAllocThread(sizeof(void*) + sizeof(struct Thread) + TH_STACK_SIZE); 
if (start == NULL) { 
    return TH_MEM; 
} 

struct Thread* th = start + TH_STACK_SIZE + sizeof(void*); 
th->alloc = start; 

size_t lockSpacePtr = (size_t)(th->lockSpace); 
lockSpacePtr += 4 - ((lockSpacePtr % 4) % 4); /* To align ptr on? at? 4 bytes */ 

th->lock = (int*)lockSpacePtr; 
*th->lock = 0; 
th->started = 0; 

th->stack = start + TH_STACK_SIZE; 
th->stackSize = TH_STACK_SIZE; 

th->fn = fn; 
th->args = args; 

Где «TH_STACK_SIZE», «fn» и «args» - «0x7fff» «ThreadCallback» и «void *» соответственно

Теперь у меня есть инициализированная структура Thread, я инициализирую PortAudio и поток по умолчанию с одним входным каналом и нулевыми выходными каналами. Тогда я начинаю свой поток

THResult thStart(struct Thread* th) { 

    int tid; 

    mutex_lock(th->lock); 

    if (th->started) { 
    mutex_unlock(th->lock); 
    return TH_RUNNING; 
    } 

    tid = clone(_thFunction, th->stack, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_IO | CLONE_SIGHAND | CLONE_THREAD, th); 

    if (tid < 0) { 
    mutex_unlock(th->lock); 
    return TH_CLONE_ERRNO; 
    } 

    th->started = 1; 
    th->tid = tid; 

    mutex_unlock(th->lock); 
    return TH_OK; 
} 

«Int _thFunction (пустота *)» в настоящее время пусто (при заполнении, он должен начать th-> п, но нет никаких проблем здесь)

И теперь, после того, позвоните в Pa_StartStream(), я могу написать все, что захочу, оно не выполнено (и, кстати, printf выходит из игры, если я его распространю в коде).

  • Я пытался выследить нарушения сегмента
  • Я снял Pa_StartStream: Он работал, но Printf был еще слишком дикий
  • я удалил старт моего потока, и все было прекрасно

Любая идея ?

EDIT 1:

  • Когда заканчивается созданный нить, программа завершается
  • GDB ничего не говорит о том, что я пытался срывы проанализировать стек, но ничего плохого в этом
+2

'printf' (и множество других функций библиотеки) ожидают, что вызывающий объект является потоком' pthread', а не задачей низкого уровня, созданной 'clone' в некотором * ad hoc * способом. – Kaz

ответ

0

Я, вероятно, понял, почему он не работает.

Я читал о том, как errno является потокобезопасным, и я думаю, что это потому, что pthread s создает потоковые локальные переменные (используемые (g) libc), моей реализации нет.

0

на разрыв dowh вопрос, есть две вещи, которые выделяются.

1) пытается вызвать printf из ad-hoc-клона. Вполне возможно, что у нас будет стандартная библиотека.

2) Обеспечение всего 4k стека.

Замените это printf(...) на звонок write(2, ...) и посмотрите, улучшилось ли поведение. У вас все еще будет головная боль на руках, но она не выйдет из-под вас немедленно.

Или, может быть, попробовать gdb

exit() закроют все темы. Возможно, вам нужно выйти другим путем. Возвращение из функции порожденного потока - плохая идея, так как это будет швырять стек основного потока.

+0

Я добавил «EDIT 1», чтобы получить более подробную информацию. Я также удалил 'printf's' из моего потока, но он все тот же. Но я не предоставляю стек 4k, это на самом деле 0x7fff = 32767B. – Juju17ification