Skip to Content.
Sympa Menu

freetds - [freetds] Memory leak or memory accumulation with freetds-0.82 ctlib's ct_cmd_alloc / ct_cmd_drop?

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: mtbrown88 AT comcast.net
  • To: freetds AT lists.ibiblio.org
  • Subject: [freetds] Memory leak or memory accumulation with freetds-0.82 ctlib's ct_cmd_alloc / ct_cmd_drop?
  • Date: Wed, 26 Nov 2008 16:40:19 +0000 (UTC)



Hi all,



Is there a known memory leak or memory accumulation issue with ct_cmd_alloc /
ct_cmd_drop?



I'm writing a program to poll a database as regular intervals and it
gradually accumulates memory (seen via top).



Below is source code to attempt and isolate the problem, compiled with the
following command:

   cc -o ctlib_leak ctlib_leak.c /usr/local/lib/libct.a /usr/lib/librt.a



I am linking with the archive libraries to run against Purify if necessary.


Quickest way to see memory eaten up (via top) is to direct stdout and stderr
to /dev/null (so output doesn't slow down processing).



Thanks in advance for any input or suggestions.  I can dig deeper, but wanted
to know if this is a known issue.



Regards, Michael





Here is the source code for ctlib_leak.c:



#include <ctpublic.h>
#include <signal.h>
#include <stdio.h>



#define DB_SERVER_PORT "crunch3.localdomain 4100"
#define DB_USER  "root"
#define DB_PASSWORD ""



#define RC_ERROR -1
#define RC_GOOD  0



#define TRUE  1
#define FALSE  0



int   signaled_to_exit;
CS_CONTEXT  *cntx_ptr;
CS_CONNECTION  *conn_ptr;
CS_COMMAND  *cmd_ptr;



void
signal_handler(int i_signal)
{
 printf("signaled received, will clean up and exit\n");
 signaled_to_exit = TRUE;
 return;

}



main()
{
 int rc;



 // setup signal handling, so program exits polling loop cleanly
 // NOTE:  NOT THREAD SAFE, SO IF MAKE MULTI-THREADED REVISIT SIGNALING
 sigset_t newmask, oldmask;
 signal(SIGINT, signal_handler); // for Ctrl-C (when run interactively)
 signal(SIGTERM, signal_handler);
 sigemptyset(&newmask);  // initialize signal set
 sigaddset(&newmask, SIGINT); // add SIGINT to signal set
 sigaddset(&newmask, SIGTERM); // add SIGTERM to signal set



 // allocate a context
 rc = cs_ctx_alloc (CS_VERSION_100, &cntx_ptr);
 if (rc == CS_SUCCEED) {
  printf("cs_ctx_alloc success\n");
 } else {
  printf("cs_ctx_alloc FAILED\n");
  return(RC_ERROR);
 }



 // initialize the library
 rc = ct_init (cntx_ptr,  CS_VERSION_100);
 if (rc == CS_SUCCEED) {
  printf("ct_init success\n");
 } else {
  printf("ct_init FAILED\n");
  return(RC_ERROR);
 }



 // allocate a connection pointer
 rc = ct_con_alloc(cntx_ptr, &conn_ptr);
 if (rc == CS_SUCCEED) {
  printf("ct_con_alloc success\n");
 } else {
  printf("ct_con_alloc FAILED\n");
  return(RC_ERROR);
 }



 // set the host and port
 rc = ct_con_props(conn_ptr, CS_SET, CS_SERVERADDR, DB_SERVER_PORT,
CS_NULLTERM, NULL);
 if (rc == CS_SUCCEED) {
  printf("ct_con_props success\n");
 } else {
  printf("ct_con_props FAILED\n");
  return(RC_ERROR);
 }



 // set the username property
 rc = ct_con_props(conn_ptr, CS_SET, CS_USERNAME, DB_USER, CS_NULLTERM,
NULL);
 if (rc == CS_SUCCEED) {
  printf("ct_con_props success\n");
 } else {
  printf("ct_con_props FAILED\n");
  return(RC_ERROR);
 }



 // set the password property
 rc = ct_con_props(conn_ptr, CS_SET, CS_PASSWORD, DB_PASSWORD, CS_NULLTERM,
NULL);
 if (rc == CS_SUCCEED) {
  printf("ct_con_props success\n");
 } else {
  printf("ct_con_props FAILED\n");
  return(RC_ERROR);
 }



 // connect to the server
 rc = ct_connect(conn_ptr, NULL, CS_UNUSED);
 if (rc == CS_SUCCEED) {
  printf("ct_connect success\n");
 } else {
  printf("ct_connect FAILED\n");
  return(RC_ERROR);
 }



 signaled_to_exit = FALSE;
 while (signaled_to_exit == FALSE) {


  //************************************************************
  // CRITICAL SECTION START -- BLOCK SIGNALS WHILE PROCESSING
  //************************************************************
  // block signals and save current signal mask
  sigprocmask(SIG_BLOCK, &newmask, &oldmask);



  rc = func();
  if (rc != RC_GOOD)
   return(rc);



  // resume the original signal mask
  sigprocmask(SIG_SETMASK, &oldmask, NULL);
  //************************************************************
  // CRITICAL SECTION END -- UNBLOCK SIGNALS, ALLOW TO EXIT
  //************************************************************
 }



 // close connection to the database
 rc = ct_close(conn_ptr, CS_UNUSED);
 if (rc == CS_SUCCEED) {
  printf("ct_close success\n");
 } else {
  printf("ct_close FAILED\n");
  return(RC_ERROR);
 }



 // deallocate the connection
 rc = ct_con_drop(conn_ptr);
 if (rc == CS_SUCCEED) {
  printf("ct_con_drop success\n");
 } else {
  printf("ct_con_drop FAILED\n");
  return(RC_ERROR);
 }



 // exit client library
 rc = ct_exit(cntx_ptr, CS_UNUSED);
 if (rc == CS_SUCCEED) {
  printf("ct_exit success\n");
 } else {
  printf("ct_exit FAILED\n");
  return(RC_ERROR);
 }



 // deallocate the context structure
 rc = cs_ctx_drop(cntx_ptr);
 if (rc == CS_SUCCEED) {
  printf("cs_ctx_drop success\n");
 } else {
  printf("cs_ctx_drop FAILED\n");
  return(RC_ERROR);
 }



 return(RC_GOOD);
}



int
func()
{
 CS_RETCODE  rc;



 // allocate a command structure
 rc = ct_cmd_alloc(conn_ptr, &cmd_ptr);
 if (rc == CS_SUCCEED) {
  printf("ct_cmd_alloc success\n");
 } else {
  printf("ct_cmd_alloc FAILED\n");
  return(RC_ERROR);
 }



/**** MEMORY LEAK OR AT LEAST ACCUMULATING ****/



 // deallocate the command structure
 rc = ct_cmd_drop(cmd_ptr);
 if (rc == CS_SUCCEED) {
  printf("ct_cmd_drop success\n");
 } else {
  printf("ct_cmd_drop FAILED\n");
  return(RC_ERROR);
 }



 return(RC_GOOD);
}





Archive powered by MHonArc 2.6.24.

Top of Page