Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Mailing Lists -> Oracle-L -> Race condition in Oracle C Interface?

Race condition in Oracle C Interface?

From: Michael Haggerty <mhagger_at_alum.mit.edu>
Date: Sun, 19 Nov 2000 17:59:03 -0500 (EST)
Message-Id: <10685.122465@fatcity.com>


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

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US