системный вызов fork вызывает ошибку сегментации - PullRequest
1 голос
/ 04 июня 2010

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

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

Ниже была трассировка стека во время прерывания fork ():

(l@5) stopped in (unknown) at 0xfe524970
0xfe524970:     <bad address 0xfe524970>
(/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) where
  [1] 0xfe524970(0xfe524970, 0x0, 0xffffffff, 0x1, 0x0, 0x0), at 0xfe52496f
  [2] run_prefork(0xfecc04b8, 0xfecc04d0, 0x242f4, 0xfea5d3c8, 0x0, 0x0), at 0xfec97ce8
  [3] _ti_fork1(0x1, 0x1ab18, 0x0, 0x0, 0x0, 0x0), at 0xfea5d3c8
  [4] _ti_fork(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfea5d50c

Кто-нибудь может описать, почему системный вызов fork () в solaris вызывает такое поведение?

Ответы [ 3 ]

1 голос
/ 04 июня 2010

Смешивание вилки и резьбы обычно не рекомендуется. Это потому, что разветвленный процесс будет иметь только один поток, поток, который вызвал fork. Все остальные потоки не существуют в новом процессе, что означает, что любые ресурсы общей памяти находятся в неизвестном состоянии. Другой поток может содержать мьютекс и никогда не освобождать его и т. Д. Существуют механизмы для смягчения этого, такие как pthread_atfork, но, как правило, вы должны только разветвиться, чтобы вызвать exec как можно скорее. при работе с несколькими потоками. Вы segfaulting в родительском процессе или новый дочерний процесс?

1 голос
/ 04 июня 2010

Дополнительно:

Возможный сценарий может быть (давайте возьмем C ++ в качестве примера):

  • создание объекта в потоке A
  • поток B вызывает метод, который вызывает fork()
  • поток A удаляет объект, пока поток B еще не запущен до запуска fork()
  • Тогда адреса памяти недействительны во время фактического вызова fork()

в зависимости от времени это может более или менее вероятно произойти. Может быть, вы можете навязать эту ситуацию, введя несколько снов ... (если вы чувствуете, что это вообще может иметь место)

Еще одной проблемой может быть аппаратный дефект. Я бы дал инструмент для проверки оперативной памяти и посмотреть, есть ли проблемы, прежде чем смотреть дальше. Дайте нам знать, если это так.

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

PS адрес at 0xfe52496f является нечетным / не кратным четырем, что не является обычным для оптимизированных программ. Это также является подсказкой в ​​отношении дефекта оперативной памяти ... Надеюсь, я ошибаюсь, с другой стороны, если я прав, вы знаете, что делать ...

0 голосов
/ 04 июня 2010

Я думаю, что ваш стек или указатель стека могли быть повреждены в тот момент, когда вы делаете вызов fork. Либо это, либо вы фактически израсходовали свое пространство стека, и указатель стека просто стесняется этого предела, прежде чем вы вызовете fork().

Вызов других функций или выделение умеренного объема памяти с помощью alloca и memset этой области до 0 непосредственно перед вызовом fork выявит, если это так, поскольку ошибка возникнет раньше.

Также возможно, что, если вы разветвляетесь в неосновном потоке процесса (я не знаком с моделью потоков Solaris, поэтому я мог бы выдумывать), вы как-то указали / распределили этот поток ( один вызов fork) стека таким образом, чтобы он не был доступен для нового процесса после разветвления.

Это повторяется? Это происходит последовательно?

...