9-й вызов клона вызывает ошибку сегмента - PullRequest
1 голос
/ 27 января 2012

У меня проблема с функцией клона в том, что она вызывает ошибку сегментации после 9-го вызова. Программа работает нормально, пока я не использую 9+ потоков.

вот мой призыв клонировать:

void **child_stack = (void **) malloc(SIGSTKSZ);
clone (func,
       (child_stack + SIGSTKSZ),
       CLONE_VM | CLONE_FILES | CLONE_PARENT_SETTID,
       (void *) argsForFunc,
       &pid);

Я использую клон, а не какую-либо библиотеку потоков более высокого уровня, такую ​​как pthreads.

Если это поможет, я получаю ошибку при использовании GDB:

Program received signal SIGSEGV, Segmentation fault.
clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:66
66              movq    %rcx,8(%rsi)
Current language:  auto; currently asm

Ответы [ 2 ]

3 голосов
/ 28 января 2012

вот мой призыв клонировать

Не делай , что . После того, как вы исправите арифметику указателя (как ответил Джей Конрод), ваш код умрет ужасной смертью из-за состояния гонки, потому что вы не настраиваете TLS (локальное хранилище потока) так, как glibc ожидает его установки. *

Фактически, если вы используете прямые clone вызовы, вы не можете когда-либо вызывать какие-либо функции glibc (даже ваши собственные функции в другой общей библиотеке (1)) в новом "потоке" или вы рискуете периодически (и чрезвычайно трудно отлаживать) сбои. Просто используйте pthread_create() вместо.

Вот ошибка glibc , показывающая виды проблем, с которыми вы столкнетесь (обратите внимание, что это , а не проблема glibc).

(1) Поскольку динамическое разрешение символов требует перехода в glibc.

2 голосов
/ 27 января 2012

Приведенный выше комментарий TJD заставил меня сразу же увидеть проблему: ваша арифметика с указателем на конец стека неверна.Если вы выделите стек как:

void **child_stack = (void **) malloc(SIGSTKSZ);

И затем вы вычислите вершину стека как:

child_stack + SIGSTKSZ

Фактический адрес, переданный клону, будет

child_stack + sizeof(void*)*SIGSTKSZ

Может быть, вы хотели, чтобы child_stack имел тип char*?sizeof(char) равно 1 по определению, так что это даст вам правильный результат.

...