Solved

Re-entrant Codes

Posted on 1998-09-22
4
407 Views
Last Modified: 2008-02-01
This code encounters an error after running < 1000 or > 1000 times. This code works in a way that messages are stored in a shared memory. I suspect that the behaviour the message is being stored or accesses the memory location is not shared.
How/where do I look into the way the message access the memory location ? Below is the code

#include <stdio.h>
#include "direcsql.h"
int EnterQueue(int line,int server, char *s, char *r,
      char *retcode,char *cols,char *rows,IQSIZE_T length, IQSIZE_T rlen)
{
//This function put the message onto the message queue that is shared.
      BOOL fInit;
      DB_TYPE smsg, rmsg;
      int i=0;

      if (line == 0)
            return -1;
      else
            line = (line*2) -2;
      hSharedQ = CreateFileMapping((HANDLE)0xFFFFFFFF,
                               NULL,
                               PAGE_READWRITE,
                               0,
                               SHMEMSIZE,
                               QUEUE_NAME);
      fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
      if (hSharedQ == NULL)
      {//Cannot allocate memory
            return -2;
      }
      else
      {
            queue = (DB_TYPE *)MapViewOfFile(hSharedQ,
                                     FILE_MAP_ALL_ACCESS,
                                     0,
                                     0,
                                     0);
            if (queue == NULL)
                  return -3;
            if (fInit)
            {
                  memset(queue, '\0', SHMEMSIZE);
            }
            if (length >= MAX_SIZE)
                  return -6;
            smsg.server = server;
            memcpy(smsg.msg,s,length);
            smsg.msg[length] = '\0';
            //Put information to my own slot.
            memcpy((queue+line),&smsg,sizeof(DB_TYPE));
            //wait for message return or time out.
            while (i < NO_OF_SECS_TO_WAIT*2)
            {
                  if (*(queue+line+1)->msg != '\0')
                  {
                        memcpy(&rmsg,(queue+line+1),sizeof(DB_TYPE));
                        memset((queue+line),'\0',sizeof(DB_TYPE));
                        memset((queue+line+1),'\0',sizeof(DB_TYPE));
                        if (r != NULL)
                        {
                              memcpy(r,rmsg.msg,rlen-1);
                      r[rlen-1] = '\0';
                        }
                        else
                              return -4;
                        if (retcode != NULL)
                              sprintf(retcode,"%02d",rmsg.retcode);
                        else
                              return -5;
                        if (cols != NULL)
                              sprintf(cols,"%02d",rmsg.cols);
                        else
                              return -6;
                        if (rows != NULL)
                              sprintf(rows,"%02d",rmsg.rows);
                        else
                              return -7;
                        return 1;
                  }
                  i++;
                  Sleep(500);
            }
            memset((queue+line),'\0',sizeof(DB_TYPE));
            memset((queue+line+1),'\0',sizeof(DB_TYPE));
            return -8;
      }
      return -9;
}
BOOL LeaveQueue()
{
//This function is called to remove the DLL from the share memory.
      if (queue != NULL)
            UnmapViewOfFile(queue);
      if (hSharedQ != NULL)
            CloseHandle(hSharedQ);
      return TRUE;
}
UDLLENTRYEXP ExecSQL(int identity,int server, char *ssql, char *rsql,
                  char *retcode,char *cols,char *rows)
{
      int r;
//This is the function called by the external program to do sending.
      if (identity > 96)
            identity = 96;
      r=EnterQueue(identity,server,ssql,rsql,retcode,cols,rows,strlen(ssql),MAX_SIZE);
      if (r == 1)
      {
            LeaveQueue();
            return 1;
      }
      else
      {
            LeaveQueue();
            return r;
      }
}

UDLLENTRYEXP ExeDirectSQL(IQVAL identity,PUSERDLLPARAM32 server,
                  PUSERDLLPARAM32 ssql, PUSERDLLPARAM32 rsql,
                  PUSERDLLPARAM32 retcode,PUSERDLLPARAM32 cols,
                  PUSERDLLPARAM32 rows)
{
      int r;
      identity++;
      if (identity > 96)
            identity = 96;
//This is the function called by the external program to do sending.
      r=EnterQueue(identity,server->u.value,ssql->u.ptr,
            rsql->u.ptr,retcode->u.ptr,cols->u.ptr,rows->u.ptr,
            ssql->length,rsql->length);
      if (r == 1)
      {
            LeaveQueue();
            return 1;
      }
      else
      {
            LeaveQueue();
            return r;
      }
}
0
Comment
Question by:Sarth
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
4 Comments
 
LVL 2

Accepted Solution

by:
mnguyen021997 earned 170 total points
ID: 1173496
a few things:

1)  you have multiple exit points ala return which can leave you in an unclean state.  either fix them by having only 1 entry & 1 exit or have automatic objects clean them up.  method 1 means instead of writing

if ( x )
   return;

dowork...

you would write

if ( !x )
{
  dowork...
}

ect.

method 2, puts cleanup code inside of the destructor of an object.  create the object on the stack and when the object code gets destroyed it will free up you resources automatically.

----

2)  the part where you "wait" for an entry to be placed in your queue should be replaced  by an event of some sort.  so instead of writing:

while ( waitsomevalue )
{
  if ( mem[x] == y )
     dosomething
}

you should write

if ( WaitForSingleObject( hEvent, sometimeoutvalue ) == WAIT_OBJECT_0 )
{
   dowork..
}

you will need to set/reset the event when mem[x] = y.
0
 

Expert Comment

by:SkyWolf
ID: 1173497
hi mnguyen... i do not fully understand what u meant bcoz i m a beginner at C++ ..so can u please teach me how to implement the WaitForSingleObject thing ? i do not understand the hEvent stuff...could you get back to mi asap ??

my mail addr is yulh@gitpl.com.sg

u help will be greatly appreciated ,,thanks!
0
 
LVL 2

Expert Comment

by:mnguyen021997
ID: 1173498
1) i assume you're using windows 95/98 or windows nt.
2) you might want to get a copy of "advanced windows nt" by jeffrey richter.  it's a great book for 32 bit programming.

events, critical sections, mutexes, semaphores are operating system objects that allows gating of who gets access to shared resources.

in the most basic terms, they're simple flags so you can essentially think of them as such.  so for example:

thread1func()
{
  while ( !done )
  {
      if ( bCanUseResource )
      {  
         bCanUseResource = false;
         dowork1( someresource );
         bCanUseResource = true;
      }
    sleep(sometime);
   }
}

thread1func()
{
  while ( !done )
  {
      if ( bCanUseResource )
      {  
         bCanUseResource = false;
         dowork2( someresource );
         bCanUseResource = true;
      }
    sleep(sometime);
   }
}


in this example, bCanUseResource acts as a gatekeeper for the shared resource (someresource).  more evident on a machine with 2 or more processors, without some sort of gating mechanism, someresource can be accessed simultaneously (by each processor) and could cause havoc on your program.  single processor machines can cause the same problems due to the multitasking nature of the OS.

events are synonimous with the bCanUseResource but the OS guarantees that when you reset or set an event you will not be interrupted (ie this procedure is atomic) and thus will have no chance for reentracy problems.

use the WaitForSingleObject() function along with CreateEvent(), ResetEvent() and SetEvent() functions to provide your gating mechanism.

WaitForSingleObject will wait on an event that has been Resetted until the event is Set again through another thread or function. so the example above translates to:

thread1func()
{
  while ( !done )
  {
      if ( WaitForSingleObject( hCanUseResource, INFINITE ) == WAIT_OBJECT_O )
       (
         ResetEvent( hCanUseResource );
         dowork1( someresource );
         SetEvent ( hCanUseResource );
      }
    sleep(sometime);
   }
}

thread1func()
{
  while ( !done )
  {
      if ( WaitForSingleObject( hCanUseResource, INFINITE ) == WAIT_OBJECT_O )
       (
         ResetEvent( hCanUseResource );
         dowork2( someresource );
         SetEvent ( hCanUseResource );
      }
    sleep(sometime);
   }
}

here hCanUseResource is created via CreateEvent() and set by the main program before the threads are spawned.
0
 

Author Comment

by:Sarth
ID: 1173499
hi mnguyen, SkyWolf is oso nick of mine ...Sarth is a nick i use from office , i use Skywolf at home...so hope u r not confuse or watever....i will try out 1st then i will get back to you say, 3 or 4 days time ? thanz !
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question