LINUX.ORG.RU

Удивительная проблема: в работающем треде вдруг меняется EIP... Help!!


0

0

Возникла удивительная проблема: в одном из тредов работающей программы вдруг, совершенно на ровном месте, меняется EIP на мусор.

Ситуация такая: запускается служебный тред, основной тред его ждёт на событии (мутекс), при этом ничего больше не делается. Тот, запущенный, начинает свою деятельность - просто обсчёт данных, при этом даже вызовов процедур не происходит. Изредка (!) - то есть от запуска к запуску - внезапно в нём происходит SIGSEGV. Дамп показывает, что всегда, при каждом развале, у этого развалившегося треда один и тот же стек, одни и те же регистры. В EIP находится мусор - число 0x9C.

Удивительно то, что на этот тред извне ничто не влияет, его не приостанавливают, ptrace не делают, и никаких setjmp/longjmp в нём не делается. При этом того числа - 0x9C в его стеке НЕТ, то есть переход в неизвестно куда по инструкции ret исключается, т.е. стек не едет.

Такое впечатление, что системный шедулер неправильно восстанавливает контекст треда. Но почему всегда в один и тот же момент, в одном и том же месте?!!

Кто-нибудь сталкивался с такой мистикой? Поможите... :_(

Система:

> uname -a
Linux z-suse92 2.6.8-24-default #1 Wed Oct 6 09:16:23 UTC 2004 i686 athlon i386 GNU/Linux

> cat /proc/cpuinfo
processor : 0
vendor_id : AuthenticAMD
cpu family : 6
model : 10
model name : AMD Athlon(tm) XP 2500+
stepping : 0
cpu MHz : 1826.970
cache size : 512 KB
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 sep mtrr pge mca cmov pat pse36 mmx fxsr sse pni syscall mmxext 3dnowext 3dnow
bogomips : 3612.67


То, что ты описываешь, больше всего похоже на затирание памяти в результате race condition. На всякий случай (чтобы исключить баги в ядре/glibc), попробуй собрать и запустить прогу на машине с другим ядром/ОС/glibc, или с LinuxThreads вместо NPTL. Если и там симптомы те же - ищи ошибку у себя. Если нет - тогда ХЗ ;(

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

Код такой:

    while(p) {
      if(p->Tag = RealVar) {
        l := p->Name;
        printf("l=%d\n", l);
      }
      p = p->Next;
      printf("p=%X\n", p);
    }

Вот он иногда работает хорошо, а иногда вдруг случается описанное.

А ещё симптом: если в коде изменить хотя бы что-нибудь, хотя бы вставить
один NOP, так, чтобы поехали адреса, - развал исчезает. 

Это тоже совершенно удивительный эффект :(

Другой процессор я ещё не пробовал (но попробую), но на LinuxThreads всё
работает прекрасно.

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

ИМХО, затертая память. У меня тоже была программа, которая на LinuxThreads работала, а на NPTL падала (правда, стабильно).

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

Было бы интересно увидеть значение 'p' при сбое. Может, у тебя там хорошо заметная однобитовая ошибка памяти ;)

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

К стати, еще одна "мелочь":
     printf("p=%X\n", p);
Для вывода значения указателя есть специальный формат - "%p".
На 32-битных будет работать, т.к. там sizeof(int)==sizeof(void*).

kosmonavt
()
Ответ на: комментарий от slav

Да, пардон за ошибки в коде. Там большие куски, которые не исполняются и не влияют на результат. Я их убрал, но вкрались опечатки. При сбое p сидит на регистре EDI, и там совершенно хороший указатель, который при отсутствии развала появляется в середине итераций.

Я тоже склоняюсь к мысли, что что-то извне портит память треда. Непонятно, как это что-то так точно коррелирует с текущей итерацией. Развал-то всегда в одном и том же месте, с одними и теми же регистрами.

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

> не исполняются и не влияют на результат

Я хочу сказать, что это действительно так, в этом нет никаких сомнений - проверено.

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