| 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);
/* 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");
Received on Sun Nov 19 2000 - 16:59:03 CST
![]() |
![]() |