Сигнал 10 (SIGBUS) в библиотеке С++ при запуске приложения в качестве демона запуска

У меня есть приложение Java, которое запускает вспомогательное приложение С++ для извлечения информации из базы данных (длинная история с участием старых 32-битных драйверов). Когда я запускаю приложение вручную, все работает отлично, приложение С++ запускается, а приложение Java использует вывод. Но когда приложение Java запускается как демон запуска, вспомогательное приложение С++ возвращается со значением выхода 138, что, я уверен, является ошибкой шины 10.

После довольно мучительной отладки я смог определить, что сигнал происходит внутри самого драйвера ODBC. Поскольку у меня нет доступа к исходному коду драйвера ODBC, мои возможности отладки ограничены.

Мой вопрос в том, что я упустил что-то в моей настройке launchd plist, которая могла бы помочь объяснить, что происходит, или происходит какая-то песочница, которая может вызвать мою проблему?

Я новичок в OSX, поэтому у меня очень мало опыта работы с launchd.

Вот моя текущая настройка plist.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
   <key>Label</key>
   <string>com.my.package.name</string>
   <key>ProgramArguments</key>
   <array>
      <string>java</string>
      <string>-cp</string>
      <string> my classpath</string>
      <string> my main class</string>
   </array>
   <key>KeepAlive</key>
   <true/>
   <key>WorkingDirectory</key>
   <string>my working directory</string>
</dict>
</plist>

Изменить: мне удалось получить файл сбоя. Вот ошибка и трассировка стека. Похоже, что dsn в ini-файле настроен правильно, но я продолжу копать.

Мне удалось получить для него файл сбоя, и вот ошибка и трассировка стека.

Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x0000000000000000

VM Regions Near 0:
--> __PAGEZERO             0000000000000000-0000000000001000 [    4K] ---/--- SM=NUL  /Users/*
    VM_ALLOCATE            0000000000001000-00000000000f7000 [  984K] ---/--- SM=NUL  

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread

0   libsystem_c.dylib               0x905c47f0 strlen + 16
1   com.4D.odbcdriver.v13           0x00308c14 _LoadOdbcIni() + 257
2   com.4D.odbcdriver.v13           0x00309546 _GetStringFromSystemDSN(char const*, char const*, char*, int) + 60
3   com.4D.odbcdriver.v13           0x0030967e SQLGetPrivateProfileStringW + 99
4   com.4D.odbcdriver.v13           0x002f0ec9 CHConnection::CreateStringFromDSN(wchar_t const*, wchar_t const*, wchar_t const*) + 225
5   com.4D.odbcdriver.v13           0x00307e4a internalSQLDriverConnectW(CHConnection*, void*, wchar_t*, short, wchar_t*, short, short*, unsigned short) + 311
6   com.4D.odbcdriver.v13           0x002fcafb SQLDriverConnectW + 129
7   org.iodbc.core                  0x0025802d SQLDriverConnect_Internal + 2381
8   org.iodbc.core                  0x00259373 SQLDriverConnect + 323

person Eric Milas    schedule 15.12.2013    source источник
comment
Ошибка автобуса? Насколько я помню, обычно это происходит из-за неправильного выравнивания указателя.   -  person Joe Z    schedule 16.12.2013
comment
Да, мне это не имеет никакого смысла. Я мог неправильно интерпретировать выходное значение 138, но то немногое, что я смог найти, указывает на ошибку шины.   -  person Eric Milas    schedule 16.12.2013
comment
Я подозреваю, что это ошибка самого драйвера, но я не могу представить, что может заставить его работать при обычном запуске, но не работать при запуске в качестве демона.   -  person Eric Milas    schedule 16.12.2013
comment
Вы вызываете код С++ через JNI? Я не понял, как способ запуска Java-приложения может привести к ошибке в коде C++   -  person Anton    schedule 16.12.2013
comment
Нет, это просто вызов оболочки через Runtime.exec()   -  person Eric Milas    schedule 16.12.2013
comment
Как приложение Java потребляет вывод?   -  person Anton    schedule 16.12.2013
comment
Он потребляет InputStream из объекта Process.   -  person Eric Milas    schedule 16.12.2013
comment
У меня возникло бы желание посмотреть, сможете ли вы собрать информацию о различиях в среде выполнения в двух случаях, возможно, запустив какой-нибудь сценарий или программу-оболочку вместо вашей цели напрямую.   -  person Chris Stratton    schedule 18.12.2013
comment
Я попытался написать скрипт, который запускает вспомогательную программу и вызывает скрипт, но получаю ту же ошибку. Использование сценария для сбора информации об окружающей среде является хорошей идеей. Я попробую это завтра, какие-либо предложения о том, что искать?   -  person Eric Milas    schedule 18.12.2013


Ответы (1)


Из трассировки стека (отформатированной для удобочитаемости ☺) довольно очевидно, что здесь происходит.

Очевидно, это драйвер 4D ODBC. Звонит strlen(). Он наткнулся на указатель NULL. strlen() была вызвана внутренней функцией библиотеки _LoadOdbcIni().

Мое обоснованное предположение состоит в том, что этот драйвер ODBC использует файл .INI и получает местоположение этого файла из переменной среды. У вас есть эта переменная среды, установленная в конфигурации вашего рабочего стола/профиле оболочки/что угодно. Но его нет в вашем plist и он не установлен, когда launchd вызывает ваш dmon.

Код в драйвере вызывает std::getenv() для получения переменной среды, которая возвращает NULL. Библиотека не была написана так, чтобы ожидать отсутствия переменной среды. Он просто вызывает strlen() для этого указателя NULL без проверки. И бах! SIGBUS и KERN_PROTECTION_FAILURE при попытке доступа к адресу 0x0000000000000000.

Узнайте из документации 4D, что бы это ни было, или из технической поддержки 4D, или из какого-либо другого источника, какие переменные среды нужны драйверу для этого файла .INI (и чего-либо еще); и установите его в свой plist. man launchd.plist кстати, как это сделать.

person JdeBP    schedule 19.12.2013
comment
Вы были правы, демоны имеют совершенно другой набор доступных переменных среды. Драйвер искал переменную USER, чтобы определить, где искать пользовательский файл odbc.ini. Как только я добавил эту переменную в файл plist, все заработало. Большое спасибо, это большой груз с моих плеч. - person Eric Milas; 20.12.2013