LINUX.ORG.RU

История изменений

Исправление firkax, (текущая версия) :

Да :) Так и было, а я почему-то без сначала отладчика, потом отладочных логов, потом отладочных логов с запоминанием обоих status2 - не догадался что происходит. Вот таких, вместо ассерта:

if(!(e1=obj->status2) || (e2=obj->status2)==4 && obj->data)) {
  log ... e1 e2
  exit(-1)
}
Ковыряние в coredump-е выдавало просто status==0 status2==0 data!=NULL, ну и я думал «вот, другой поток просто успел всё доделать пока assert выводил ошибку в stderr, потому данные на момент ассерта я не увижу».

Но удивляет вот что: сравнение сначала с нулём, а затем с четвёркой - это почти соседние ассемблерные инструкции получаются. Интуитивно кажется, что вероятность между ними вклиниться status2=0; исчезающе мала, однако на практике оно весьма себя проявляет. Конечно, даже если бы вероятность и правда была незаметной, это был бы совсем не повод оставлять этот баг, но то что он вот так себя заметно проявил - это удивительно. И, наверно, хорошо - ведь иначе он остался бы в коде и проявился когда-нить спустя годы, и пришлось бы вспоминать что там вообще происходит. Исправил добавлением write-lock1 вокруг status2=0;.

но это если компилятор не взял на регистр status2… короче это место точно непонятное.

Там -O0, по крайней мере сейчас.

Исправление firkax, :

Да :) Так и было, а я почему-то без сначала отладчика, потом отладочных логов, потом отладочных логов с запоминанием обоих status2 - не догадался что происходит. Вот таких, вместо ассерта:

if(!(e1=obj->status2) || (e2=obj->status2)==4 && obj->data)) {
  log ... e1 e2
  exit(-1)
}
Ковыряние в coredump-е выдавало просто status==0 status2==0 data!=NULL, ну и я думал «вот, другой поток просто успел всё доделать пока assert выводил ошибку в stderr, потому данные на момент ассерта я не увижу».

Но удивляет вот что: сравнение сначала с нулём, а затем с четвёркой - это почти соседние ассемблерные инструкции получаются. Интуитивно кажется, что вероятность между ними вклиниться status2=0; исчезающе мала, однако на практике оно весьма себя проявляет. Конечно, даже если бы вероятность и правда была незаметной, это был бы совсем не повод оставлять этот баг, но то что он вот так себя заметно проявил - это удивительно. И, наверно, хорошо - ведь иначе он остался бы в коде и проявился когда-нить спустя годы, и пришлось бы вспоминать что там вообще происходит. Исправил добавлением write-lock1 вокруг status2=0;.

Исходная версия firkax, :

Да :) Так и было, а я почему-то без сначала отладчика, потом отладочных логов, потом отладочных логов с запоминанием обоих status2 - не догадался что происходит. Вот таких, вместо ассерта:

if(!(e1=obj->status2) || (e2=obj->status2)==4 && obj->data)) {
  log ... e1 e2
  exit(-1)
}

Но удивляет вот что: сравнение сначала с нулём, а затем с четвёркой - это почти соседние ассемблерные инструкции получаются. Интуитивно кажется, что вероятность между ними вклиниться status2=0; исчезающе мала, однако на практике оно весьма себя проявляет. Конечно, даже если бы вероятность и правда была незаметной, это был бы совсем не повод оставлять этот баг, но то что он вот так себя заметно проявил - это удивительно. И, наверно, хорошо - ведь иначе он остался бы в коде и проявился когда-нить спустя годы, и пришлось бы вспоминать что там вообще происходит. Исправил добавлением write-lock1 вокруг status2=0;.