Может ли процесс как-то продолжаться без сбоев после получения SIGSEGV или SIGBUS?

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

ОБНОВЛЕНИЕ (краткое изложение моего дела):

Мне нужен очень быстрый доступ к файлу. С этой целью я вызываю mmap(2), чтобы сопоставить этот файл со всеми процессами, обращающимися к нему. Данные, которые я записываю в файл, имеют форму определенной структуры данных и потребляют много памяти. Поэтому, если наступит момент, когда размера, который я сопоставил, недостаточно, мне нужно увеличить размер файла и снова выполнить mmap(2) этот файл с новым размером. Для увеличения размера я вызываю ftruncate(2). ftruncate(2) может вызываться из любого процесса, поэтому вместо этого он может сжать файл. Поэтому мне нужно проверить, не приводит ли память, к которой я обращаюсь, к ошибкам seg. Я работаю на macOS.

Вы можете сделать это: stackoverflow.com/questions/2663456/…, но это будет очень плохой дизайн.

Eugene Sh. 21.05.2019 17:14

Этот подход неверен. Вам нужно избегать segfault. Как только вы это получите, обычно уже слишком поздно. Segfault означает примерно: где-то в вашей программе есть ошибка, и все пошло не так.

Jabberwocky 21.05.2019 17:15

Я бы предложил использовать базу данных для того же, например sqlite

Mayur 21.05.2019 17:16

Если ваши «данные могут быть обновлены откуда угодно», вам необходимо реализовать надлежащий механизм синхронизации.

Eugene Sh. 21.05.2019 17:17

@ЕвгенийШ. Я не уверен, правильно ли я это понял. Пожалуйста, скажите мне, если я ошибаюсь. Означает ли это, что после вызова обработчика сигнала строка кода, вызвавшая появление этого сигнала, выполняется снова, и в следующий раз, если она не вызовет ошибку установки, программа не рухнет?

Mihir Luthra 21.05.2019 17:21

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

Mihir Luthra 21.05.2019 17:21

Я обновил вопрос. Есть ли лучший способ добиться того же?

Mihir Luthra 21.05.2019 17:35
Мне нужен очень быстрый доступ к файлу. Тогда зачем использовать файл? Это ненужные накладные расходы. Если вам нужен «чрезвычайно быстрый доступ», вы можете просто использовать что-то вроде общей памяти SysV и удалить накладные расходы, связанные с файловой системой. Если данные слишком велики, чтобы поместиться в память, ваше решение mmap() будет иметь серьезные проблемы с производительностью, поскольку страницы все равно придется выгружать в память и извлекать из нее.
Andrew Henle 21.05.2019 18:18

@AndrewHenle, это недоступно в macOS. Извините, что не упомянул об этом в моем вопросе. Я обновлю его прямо сейчас.

Mihir Luthra 21.05.2019 18:21

Другая проблема с общей памятью SysV заключается в том, что она не поддерживает изменение размера объекта общей памяти. Большинство систем, отличных от SysV (я полагаю, включая OSX), в любом случае эмулируют общую память SysV с файлами mmaped. Использование mmap в файловой системе tmpfs (память) работает настолько быстро, насколько это возможно.

Chris Dodd 21.05.2019 19:15
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
10
717
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Когда какой-либо процесс хочет обновить размер, он берет блокировку записи, считывает текущее значение, увеличивает его, msync просматривает страницу (использования MS_ASYNC|MS_INVALIDATE должно быть достаточно), тогда использует ftruncate для увеличения файла, затем увеличивает свое отображение файла, и только потом снимает блокировку записи. Если после снятия блокировки записи вы обнаружите, что файл уже больше нужного вам размера, просто увеличьте отображение и снимите блокировку, не вызывайте ftruncate и не изменяйте поле.

Это гарантирует, что взаимодействующие процессы никогда не сделают файл меньше, а область памяти, отображаемая каждым процессом, всегда поддерживается выделенным хранилищем, поэтому вы никогда не должны получать никаких SIGBUSes. Обратите внимание, что благодаря волшебству разреженные файлы размер файла на диске будет увеличиваться только тогда, когда вы на самом деле записываете во вновь выделенное пространство.

Ответ принят как подходящий

Да, вы можете заставить это работать с обработчиком сигнала, который ловит SIGSEGV или SIGBUS, настраивает mmap и возвращает. Когда обработчик сигнала возвращается, он возобновляет работу с того места, где произошел сигнал, что означает, что для синхронного сигнала, такого как SIGSEGV или SIGBUS, он повторно запустит инструкцию, вызвавшую ошибку.

Вы можете увидеть это в моей реализации общая память malloc — найдите shm_segv в malloc.c, чтобы увидеть обработчик сигнала; это довольно просто. Я никогда не пробовал этот код на MacOS, но я думаю, что он будет работать на OSX, поскольку он работает на всех других UNIX-системах, производных от BSD, на которых я его пробовал. Есть проблема, что, согласно спецификации POSIX, mmap не является асинхронно безопасным, поэтому его нельзя вызывать из обработчика сигналов, но на всех системах, которые фактически поддерживают реальное отображение памяти (а не его эмуляцию с помощью malloc+read), это должно быть отлично.

Другие вопросы по теме