Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
Home -> Community -> Mailing Lists -> Oracle-L -> Race condition in Oracle C Interface?
I am trying to use Oracle in a multithreaded application that creates
and destroys multiple database connections. It seems to have tickled
a bug in Oracle, though, because the application hangs up deep in
Oracle. I simplified the application into the trivial C program
appended below, which on my system locks up about half of the time.
It just opens up two database connections and some associated
structures and then closes them. I don't think there is a problem
with code, but if you are sceptical just take a look; it is quite
trivial.
Has anybody seen this problem? Does anyone know a workaround?
I am running Oracle 8.1.6.1 under Linux/Intel with kernel version 2.2.14. The program locks up within OCIServerDetach and has to be kill -6'ed or stronger. Only the client seems to lock up; the server seems unaffected.
Thanks,
Michael
-- Michael Haggerty mhagger_at_alum.mit.edu /* ==================== main.c ======================== */ /* compile with: gcc -I/ora8/m01/app/oracle/product/8.1.6/rdbms/demo -I/ora8/m01/app/oracle/product/8.1.6/network/public -I/ora8/m01/app/oracle/product/8.1.6/plsql/public -I/ora8/m01/app/oracle/product/8.1.6/rdbms/public -DORACLE8i -g -o main -L/ora8/m01/app/oracle/product/8.1.6/lib/ -lclntsh -Wl,-rpath,/ora8/m01/app/oracle/product/8.1.6/lib ./main.c */ #include <assert.h> #include <stdio.h> #include <string.h> #include <malloc.h> #include <oci.h> typedef struct { OCIEnv *envhp; /* Environment handle */ OCIError *errhp; /* Error handle */ OCIServer *srvhp; /* Server handle */ OCISession *usrhp; /* User handle */ OCISvcCtx *svchp; /* Service Context */ } ServerContext; ServerContext *Connect(char *user, char *password, char *database) { ServerContext *sc; int userlen; int passwordlen; int databaselen; sword status; sword credentials = OCI_CRED_RDBMS; userlen = strlen(user); passwordlen = strlen(password); databaselen = strlen(database); sc = (ServerContext *)malloc(sizeof(ServerContext)); sc->envhp = NULL; sc->errhp = NULL; sc->svchp = NULL; sc->srvhp = NULL; sc->usrhp = NULL; status = OCIEnvCreate(&sc->envhp, OCI_THREADED, NULL, NULL, NULL, NULL, 0, NULL); assert(status == OCI_SUCCESS);Received on Sun Nov 19 2000 - 16:59:03 CST
/* Allocate the error handle */
status = OCIHandleAlloc(sc->envhp, (dvoid **)&sc->errhp, OCI_HTYPE_ERROR, 0, NULL); assert(status == OCI_SUCCESS);
/* Allocate the server handle */
status = OCIHandleAlloc(sc->envhp, (dvoid **) &sc->srvhp, OCI_HTYPE_SERVER, 0, NULL); assert(status == OCI_SUCCESS);
/* Connect to database */
status = OCIServerAttach(sc->srvhp, sc->errhp, database, databaselen, OCI_DEFAULT); assert(status == OCI_SUCCESS);
/* Allocate a service context */
status = OCIHandleAlloc(sc->envhp, (dvoid **) &sc->svchp, OCI_HTYPE_SVCCTX, 0, NULL); assert(status == OCI_SUCCESS);
/* Attach the server to the service context */
status = OCIAttrSet(sc->svchp, OCI_HTYPE_SVCCTX, (dvoid *) sc->srvhp, (ub4) 0, OCI_ATTR_SERVER, sc->errhp); assert(status == OCI_SUCCESS);
/* Allocate a session */
status = OCIHandleAlloc(sc->envhp, (dvoid **) &sc->usrhp, OCI_HTYPE_SESSION, 0, NULL); assert(status == OCI_SUCCESS);
/* Were credentials provided? if so, set them in the session */
status = OCIAttrSet(sc->usrhp, OCI_HTYPE_SESSION, (dvoid *) user, (ub4) userlen, OCI_ATTR_USERNAME, sc->errhp); assert(status == OCI_SUCCESS); status = OCIAttrSet(sc->usrhp, OCI_HTYPE_SESSION, (dvoid *) password, (ub4) passwordlen, OCI_ATTR_PASSWORD, sc->errhp); assert(status == OCI_SUCCESS);
/* Now begin the session */
status = OCISessionBegin(sc->svchp, sc->errhp, sc->usrhp, credentials, OCI_DEFAULT); assert(status == OCI_SUCCESS);
/* Now attach the session to the service context */
status = OCIAttrSet(sc->svchp, OCI_HTYPE_SVCCTX, sc->usrhp, 0, OCI_ATTR_SESSION, sc->errhp); assert(status == OCI_SUCCESS); return sc; } /* ** ServerContext_dealloc ** ** Called when a server context goes out of scope; hang up the connection ** to the database! */ void ServerContext_dealloc(ServerContext *self) { sword status;
/* End the session */
assert(self->svchp); status = OCISessionEnd(self->svchp, self->errhp, self->usrhp, OCI_DEFAULT); assert(status == OCI_SUCCESS);
/* Disconnect from the server */
assert(self->srvhp); status = OCIServerDetach(self->srvhp, self->errhp, OCI_DEFAULT); assert(status == OCI_SUCCESS);
/* Deallocate the session handle */
assert(self->usrhp); status = OCIHandleFree(self->usrhp, OCI_HTYPE_SESSION); assert(status == OCI_SUCCESS);
/* Deallocate the server handle */
assert(self->srvhp); status = OCIHandleFree(self->srvhp, OCI_HTYPE_SERVER); assert(status == OCI_SUCCESS);
/* Deallocate the service context handle */
assert(self->svchp); status = OCIHandleFree(self->svchp, OCI_HTYPE_SVCCTX); assert(status == OCI_SUCCESS);
/* Deallocate the error handle */
assert(self->errhp); status = OCIHandleFree(self->errhp, OCI_HTYPE_ERROR); assert(status == OCI_SUCCESS);
/* Deallocate the environment handle */
assert(self->envhp); status = OCIHandleFree(self->envhp, OCI_HTYPE_ENV); assert(status == OCI_SUCCESS); free(self); } int main(int argc, char *argv[]) { char *user; char *password; char *database; ServerContext *db1; ServerContext *db2; assert(argc == 4); user = argv[1]; password = argv[2]; database = argv[3]; db1 = Connect(user, password, database); db2 = Connect(user, password, database); fprintf(stderr, "Deleting db2.\n");