Многопроцессорная обработка Python, не учитывающая LD_LIBRARY_PATH для динамической загрузки

Я работаю над проектом Python 3.5, который использует многопроцессорность, рабочий процесс должен иметь возможность вызывать скомпилированный код MATLAB. Чтобы не устанавливать переменную среды LD_LIBRARY_PATH перед запуском python (это вызывает конфликты с libexpat), я хочу, чтобы только этот рабочий процесс использовал измененный LD_LIBRARY_PATH. Я подумал, что это будет работать нормально, так как процессы, созданные с fork() запускаются с любыми изменениями среды, внесенными в родительский. я использую

matlab_runtime_paths = [
    '/usr/local/MATLAB/MATLAB_Runtime/v91/runtime/glnxa64',
    '/usr/local/MATLAB/MATLAB_Runtime/v91/bin/glnxa64',
    '/usr/local/MATLAB/MATLAB_Runtime/v91/sys/os/glnxa64',
    '/usr/local/MATLAB/MATLAB_Runtime/v91/sys/opengl/lib/glnxa64'
]
system_lib_dir = '{}/lib'.format(sys.prefix)

lib_paths = matlab_runtime_paths + [system_lib_dir]
lib_paths_format = ':'.join(lib_paths)
os.putenv('LD_LIBRARY_PATH', lib_paths_format)

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

def matlab_worker(matlab_pipe_end):
    import service
    service.initialize_stub()

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

def matlab_worker(matlab_pipe_end):
    os.system('echo $LD_LIBRARY_PATH')
    import service
    service.initialize_stub()

переменная установлена, я могу даже сделать

def matlab_worker(matlab_pipe_end):
    os.system('ldd <path>/service.so')
    import service
    service.initialize_stub()

и убедитесь, что все общие объекты разрешены, но python не может выполнить эту настройку, что приводит к сбою при импорте. Я предполагаю, потому что динамический загрузчик не перечитывает переменную LD_LIBRARY_PATH после разветвления (это может быть правильно? Это не звучит правильно, но я не могу найти какую-либо документацию по этому поводу)

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

1 ответ

Решение

Я предполагаю, потому что динамический загрузчик не перечитывает переменную LD_LIBRARY_PATH после разветвления

Это правда, к тому времени, когда вы звоните putenv динамический компоновщик уже проанализирован LD_LIBRARY_PATH и построил свои внутренние таблицы для разрешения символов. Вы не сможете восстановить те без exec,

Кроме того, вы можете

  • при запуске посмотрите, были ли заданы пути, а если нет, установите их и повторноexec сценарий
  • изменить рабочие сценарии на автономные, чтобы они могли быть execскорее, чем fork-ed
  • начните свое главное приложение с LD_LIBRARY_PATH задавать
  • вручную загрузить необходимые библиотеки через dlopenиспользуя абсолютные пути
Другие вопросы по тегам