Multi-threading & obreak() / OCIBreak() calls block on NT

From: Nick Rumble <rumbln_at_tetraworld.com>
Date: Mon, 27 Apr 1998 13:23:14 +0100
Message-ID: <893679582.1934.0.nnrp-04.c2d9cf02_at_news.demon.co.uk>



I'm trying to implement a "statement timeout" mechanism within OCI to allow "SELECT FOR UPDATE" statements (and others) to timeout after a defined period of time (# of seconds).

Unix implementation

I've implemented this mechanism on various Unix O/Ss using the Unix alarm() & signal(SIGALRM, trapfunc) system calls to define a function to be called after oexec() has blocked for a specified number of seconds.

The alarm trap function calls obreak() thus "cancelling" the blocking oexec() call.

This code works fine.

NT implementation.

NT doesn't support the alarm() system call, nor does it support many of the Unix signal types - including SIGALRM. To remidy this I've implemented alarm() for NT(Win32) using a thread (created via WIN32 call _beginthread()). The thread is used to sleep for a period of time (as the Unix alarm() call does) and then to raise a signal once this time period expires. The only trappable signal on NT is SIGINT so instead of trapping SIGALRM, I trap SIGINT.

I've tested this code in isolation from OCI and it works fine.

However, in the OCI environment, when the trap function calls obreak() it blocks.

Using opinit()

The above implementation does not take into account the fact that I'm calling OCI from two different threads. I therefore changed my implementation to call

opinit(OCI_EV_TSF) before calling olog() to tell OCI to expect multi-threaded calls. Unfortunately, the result was the same - obreak() blocks.

OCI 8 API. My final attempt was to use the OCI 8. calls instead of opinit() to initialise the OCI layer. The main calls are:

OCIInitialize(OCI_THREADED, ...)
OCIEnvInit(&OCIEnvp, OCI_ENV_NO_MUTEX, ...); OCILogon(OCIEnvp, OCIErrp, &OCISvcp, ...); OCISvcCtxToLda(OCISvcp, &LDA);

I use the last call to generate the LDA (OCI 7.3 compatible) structure so I can continue to use the 7.3 API. The rest of the code remains the same.

I've used the OCI_ENV_NO_MUTEX flag because:

  1. I don't want the overhead of the thread-safe OCI driver.
  2. The only place I need to utilise multiple-threads is in this area.

Again the results were the same - obreak() blocks.

Non-blocking API

I don't really want to use the non-blocking API because I believe this would be an overhead as I have to make one call to execute the statement (or fetch a row etc) and another call to test to see if the call has completed. Normally the call will complete immediately, it is the expection to the norm. that I'm having to cater for.

Any feedback is appreciated

Regards

Nick Received on Mon Apr 27 1998 - 14:23:14 CEST

Original text of this message