Question

I have a Java application that launches a c++ helper application to retrieve information from a database (long story involving old 32 bit drivers). When I run the application manually, everything works perfectly, the c++ app runs and the Java app consumes the output. But when the java app runs as a launchd daemon the c++ helper app is returning with an exit value of 138, which I am pretty sure is a bus error 10.

After some pretty painful debugging, I have been able to determine that the signal is happening inside the ODBC driver itself. Since I don't have access to the source for the ODBC driver, my debugging options are limited.

My question is, am I missing anything in my launchd plist setup that could help explain what is happening or is there some sort of sandboxing going on that could be causing my problem?

I am an OSX novice, so I have very little experience with launchd in general.

Here is my current plist setup.

<?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>

Edit: I was able to get a crash file. Here is the error and stack trace. The dsn does appear to be set up correctly in the ini file, but I will keep digging.

I was able to get a crash file for it and here is the error and stack trace.

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
Was it helpful?

Solution

It's fairly obvious from the stack trace (when formatted for legibility ☺) what's going on here.

That's apparently the 4D ODBC driver. It's calling strlen(). It has hit a NULL pointer. strlen() was called by a library-internal _LoadOdbcIni() function.

My educated guess is that that ODBC driver uses an .INI file, and that it gets the location of that file from an environment variable. You've got that environment variable set in your desktop configuration/shell profile/whatever. But it's not in your plist and not set when launchd invokes your dæmon.

The code in the driver calls std::getenv() to get the environment variable, which returns NULL. The library wasn't written to expect the environment variable to be missing. It's simply calling strlen() on that NULL pointer without checking for it. And — bang! — SIGBUS and KERN_PROTECTION_FAILURE when trying to access address 0x0000000000000000.

Find out from the 4D doco, whatever that is, or from 4D technical support, or from some other source, what environment variables are needed by the driver for that .INI file (and anything else); and set it in your plist. man launchd.plist for how to do that, by the way.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top