OCCI with CGI and FastCGI on Apache, Solaris and Windows

by Peter Moss 27. July 2010 18:19

Hopefully this article will save someone a little bit of time trying to get OCCI to work with CGI on Solaris. It is one of those things that is not documented (until now) anywhere, but can be "learned" the hard way.

Recently, I had to use Oracle OCCI library in an Apache CGI program for one of my clients. Sounds like a simple task. I went out and hacked away a simple test driver to test the OCCI libraries:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <iostream>
#include "fcgi_stdio.h"
#include <occi.h>

using namespace oracle::occi;
using namespace std;

void run(void)
{
try
{
int rc = 0;
printf("Content-type: text/html\r\n");
printf("pragma: no-cache\r\n\r\n");
printf("<html><title>cgitest FAST CGI</title><body><pre>\r\n\r\n");

time_t t;
t = time(NULL);

struct tm * st;
st = localtime(&t);
printf("Time: %s", asctime(st));
printf("uid: %d gid: %d\r\n\r\n", getuid(), getgid());

printf("Calling Environment::createEnvironment()...\r\n");
Environment* ora = Environment::createEnvironment();
printf("Environment::createEnvironment() returned: 0x%p\r\n", ora);
printf("\r\n\r\n");

Environment::terminateEnvironment(ora);

printf("Test completed!!!</pre></body></html>\r\n");
} catch (SQLException oraException)
{
int eno = oraException.getErrorCode();
string errmsg = oraException.getMessage().c_str();
printf("\r\nfailed to create Oracle environment, errno: %d errmsg: %s\r\n",
eno, errmsg.c_str());
} catch (...)
{
printf("\r\nCaught unhandled exception...\r\n");
}
}

int main(int argc, char * argv[])
{
while(FCGI_Accept() >= 0)
run();

return 0;
}; // end of main()

Well, on Windows it works like a charm, but on Solaris, well it is a different story. It executes fine from the command line but fails when invoking it through a browser as a CGI program. I've tried different OCCI versions, releases, patches, tried it on Solaris 8, tried it on Solaris 10, with the same result. OCCI library crashed with unhandled exception, a core file to be precise :-) No C++ exceptions for you, just an old fashioned core file.

The 64 bit stack looked like this:

(dbx) where
current thread: t@1
[1] OCIPClearMxCtr(0xffffffff7f600000, 0xffffffff7cfeb638, 0x1328, 0xffffffff7ce41530,
0x198448, 0x0), at 0xffffffff7d374388
[2] oracle::occi::OCCIErrorGet(0xffffffff7f600000, 0x1, 0x0, 0x100155b98,
0xffffffff7fffee10, 0x400), at 0xffffffff7ce50f48
[3] oracle::occi::SQLExceptionImpl::SQLExceptionImpl(0x100155b80, 0x0,
0xffffffff7f600000, 0x1, 0x1400, 0x1a8ac4), at 0xffffffff7ce41530
[4] oracle::occi::SQLExceptionCreate(0xffffffff7ca0dfc8, 0xffffffff7f600000, 0x1, 0x0,
0x1a5ac4, 0xffffffff7c905660), at 0xffffffff7ce4450c
[5] oracle::occi::Environment::createEnvironment(0x0, 0x0, 0x0, 0x0, 0x1a5694,
0xffffffff7ca0dfc8), at 0xffffffff7ce44940
[6] run(), line 42 in "cgitest.cpp"
[7] main(argc = 1, argv = 0xffffffff7ffff608), line 53 in "cgitest.cpp"

The 32 bit stack was pretty much the same:

(dbx)  current thread: t@  
[1] OCIPClearMxCtr(0x64, 0xff14b560, 0x9b0, 0xff0b57d4, 0x891bc, 0x800), at 0xfe2a72a4
[2] oracle::occi::OCCIErrorGet(0x64, 0x1, 0x0, 0x6e55c, 0xffbef100, 0x400), at 0xff0c19f8
[3] oracle::occi::SQLExceptionImpl::SQLExceptionImpl(0x6e550, 0xff14c044, 0x64, 0x1,
0x800, 0x96c74), at 0xff0b4948
[4] oracle::occi::SQLExceptionCreate(0xff25b190, 0x64, 0x1, 0x0, 0x944fc, 0xff14c044),
at 0xff0b70a0
[5] oracle::occi::Environment::createEnvironment(0x0, 0x0, 0x0, 0x2478c, 0x941f8,
0xff25b190), at 0xff0b73a8
[6] run(), line 42 in "cgitest.cpp" [7] main(argc = 1, argv = 0xffbef794), line 53 in
"cgitest.cpp"

First thing was to make sure LD_LIBRARY_PATH or LD_LIBRARY_PATH_32 were setup correctly. BTW, I've tried 32 bit and 64 bit versions out of desperation.  Still, the OCCI libraries refused to work when invoked as CGI programs.

At some point I thought, the user or group permissions (CGIs are run under "nobody" account by default) caused this nasty crash. So I changed User and Group directives in httpd.conf.  This did not help.

The solution was quite simple, but it took me almost a day of testing with different environments to figure this one out. Apparently, OCCI libraries make use of ORACLE_HOME environment variable.  Not sure what for, but ORACLE_* environment variables are not passed on to Apache CGI programs by default.  This is Solaris thing only, as on Windows the environment variables are visible to CGI programs.  Actually a pretty small subset of environment variables is actually passed on to CGI programs on Solaris.

To add ORACLE_* environment variables to the CGI environment, I've added the following lines in the httpd.conf:

SetEnv ORACLE_BASE  /devtools/oracle/10.2
SetEnv ORACLE_HOME /devtools/oracle/10.2
SetEnv ORACLE_SID  DEVDB10GR2

After apachectl restart, all started to work like a magic :-)  BTW, Oracle support was of no help :-(  Clueless to be exact.  Like I was.

I wish developers at Oracle checked ORACLE_* environment variables and if not set, just throw a nice ORA-* exception, but I guess that is too much to ask.

Tags:

Add comment




biuquote
  • Comment
  • Preview
Loading