LINUX.ORG.RU

pthread_kill всегда приводит к ошибке сегментирования

 


2

2

Всех приветствую. Проблема такая:

1.c
#include 2.h
...
void main()
...
    pthread_create( &thread_id[0], NULL, &abc, NULL );
    pthread_create( &thread_id[1], NULL, &def, NULL );
...
2.c
...
switch (i) {
        case 0:
            return -1;
        break;
        case 1:
            pthread_kill(thread_id[1], 70 );
        break;
        case 2:
            pthread_kill(thread_id[1], 71 );
        break;
    }
...
2.h
...
pthread_t thread_id[2];
...
3.c
...
void * def() {
	signal(70, cont_slave);
	signal(71, cont_master);
	signal(72, exit);
	while (1) {
		sleep(2);
		fprintf(stderr, "thread alive\n");
	}
}
...

такие конструкции всегда при обработке дают ошибку сегментирования. поток запускается нормально, как только вызывается kill, всё падает.

Что читать и ковырять?

★★

Последнее исправление: chenger (всего исправлений: 1)
Ответ на: комментарий от LamerOk

если я скажу что pthread_kill(thread_id[1], 0 ); также вызывает сегфолт, не смотря на то что должен просто вернуть ошибку, более умные мысли будут?

chenger ★★
() автор топика
Ответ на: комментарий от chenger

Запусти программу в отладчике и убедись, что thread_id[1] там, где ты нить создаёшь имеет одно значение, а thread_id[1] там, где ты pthread_kill зовёшь, другое. Во втором случае будет NULL, поэтому и падает.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

да, NULL. а как его тогда передать чтобы управлять этим тредом? тред-то жив.

Извиняюсь за тупые вопросы.

chenger ★★
() автор топика
Ответ на: комментарий от chenger

а как его тогда передать

Ты сделал две копии массива thread_id, по одной в каждой единице трансляции. Нужно сделать так, определение было только в одной единице трансляции, а декларации — во всех использующих. Это можно сделать, используя extern.

Извиняюсь за тупые вопросы.

Проблема не в тупых вопросах. Проблема в том, что ты не пытаешься на них сам найти ответ. Вот, скажем, по твоей проблеме, даже не зная деталей, можно найти ответ по запросу «c global variable is zero in other c file» в гугле. Буквально первым же результатом.

Ну и рекомендую что-нибудь почитать про язык, на котором программируешь.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

спасибо, нне так задавал вопросы гуглу. буду разбираться.

Основная проблема в том что надо «сейчас вот срочно вкорячить вот это сюда»...

chenger ★★
() автор топика
Ответ на: комментарий от chenger

срочно

На «срочно» времени уйдёт больше, чем на «неспешно».

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Ты сделал две копии массива thread_id, по одной в каждой единице трансляции.

Не понимаю как у него могло это получиться успешно, линкер же не даст собрать такую программу из-за повторного определения символа.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

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

zaz ★★★★
()
Ответ на: комментарий от xaizek

Хм... Как я понял, так в ld можно. Если не инициализировать, переменная становится common symbols, и при компоновке ld их мержит. Я попробовал в двух файлах одно и то же имя объявить, отдельно скомпилить, а потом слинковать. И это даже работает, можно в одном файле установить, а в другом прочитать.

Получается, у ТС проблема вызвана очерёдностью вызовов.

i-rinat ★★★★★
()
Ответ на: комментарий от zaz

Так компилятор не имеет право это делать в этом случае, переменная же не static, их нельзя выкидывать. Если бы у переменной был инициализатор, то это было бы определение, а так это только объявление и переменная будет в общей секции, которую линкер смержит (я проверил по map-файлу линкера) и всё будет работать как ТС ожидал. Я просто усомнился в диагнозе проблемы, так как она бы дала ошибку сборки.

xaizek ★★★★★
()
Ответ на: комментарий от i-rinat

Должно в любом линкере быть можно, я не вижу проблем с точки зрения языка. Просто тоже попробовал и не понял то ли у меня не то, то ли у ТС что-то другое.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Например можно добавить static :)

Видел забавный баг - в двух единицах трансляции были объявлены одноименные классы, с разными сигнатурами статических методов.

Точно не помню в чём именно был затык,но реализации этих классов таки умудрились подраться. А линкер ничего не заметил, с его точки зрения это было определение методов одного класса в разных единицах трансляции.

upd: прочитал внимательней хедпост, там нет static, тогда мне тоже интересно как так?

pon4ik ★★★★★
()
Последнее исправление: pon4ik (всего исправлений: 1)
Ответ на: комментарий от xaizek

Должно в любом линкере быть можно

У ld есть опция — ругаться на такое. Создаётся ощущение, что это всё же немного порицается.

i-rinat ★★★★★
()
Ответ на: комментарий от pon4ik

Точно не помню в чём именно был затык

Тут? Там же одинаковые сигнатуры вроде были.

тогда мне тоже интересно как так?

Работает через common symbols в линкере:

int i;

A common symbol.  If there are only (one or more) common symbols for a variable, it goes in the uninitialized data area of the output file.  The linker merges multiple common symbols for the same variable into a single symbol.  If they are of different sizes, it picks the largest size.  The linker turns a common symbol into a declaration, if there is a definition of the same variable.

xaizek ★★★★★
()
Ответ на: комментарий от i-rinat

Да, и объяснение там неплохое (--warn-common, если кому интересно). Я в стандарте поискал и в итоге оказалось, что это популярное расширение:

J.5.11 Multiple external definitions

There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).

xaizek ★★★★★
()
Последнее исправление: xaizek (всего исправлений: 1)
Ответ на: комментарий от xaizek

Точно, тут. Жалко код примера утерян, что то я не додумался в какой нить сниппет движок нормальный кинуть.

Спасибо за пояснение.

В том топике меня скорее интересовало не почему так, а как запретить линкеру так делать :)

pon4ik ★★★★★
()
Ответ на: комментарий от xaizek

Ы! Пойду поправлю для подержания порядку :)

pon4ik ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.