Thread: Need help woth thread support in ecpglib

Need help woth thread support in ecpglib

From
Michael Meskes
Date:
Hi,

I recently got the following bug report. It appears to be a bug in
pthread implementation in ecpglib/connect.c where 

pthread_getspecific(actual_connection_key);

doesn't return the value of actual_connection, the variable used for
non-threaded mode. Problem is I never really used threading in my apps
and didn't do the threading patches. Maybe someone with more knowledge
than me could have a look at this. Thanks.

Michael

---

When using postgresql 8.0 compiled with --enable-thread-safety, new threads
no longer see the default ecpg connection.  That was not the case in 7.4.x
compiled with or without --enable-thread-safety.

TEST CASE

The program at the end of this mail sets up a database table named
"dbthreadtest" in the default database.  It then spawns 5 threads which each
do a select from that table using the default connection.

If the program is saved as dbthreadtest.pgc, compile with:

ecpg -t -o dbthreadtest.c dbthreadtest.pgc
gcc -Wall -o dbthreadtest dbthreadtest.c -lecpg -lpthread

Results under 7.4.x / 8.0 without --enable-thread-safety:

got id = 1
got id = 1
got id = 1
got id = 1
got id = 1

Results under 8.0 with --enable-thread-safety:

'No such connection NULL in line 76.', sqlcode = -220 select id

TEST PROGRAM

/* -*-C-*- */

#include <stdlib.h>
#include <pthread.h>

#define CHECK_SQL(fmt, args...)                \
do                            \
{                            \ if (sqlca.sqlcode != ECPG_NO_ERROR)            \   {                            \
fprintf(stderr, "'%s', sqlcode = %ld " fmt "\n",    \       sqlca.sqlerrm.sqlerrmc,            \       sqlca.sqlcode,
##args);            \     exit (1);                        \   }                            \}
 \
 
while (0)

#define FATAL(fmt, args...)            \
do                        \
{                        \ fprintf (stderr, fmt "\n", ## args);        \ exit (1);                    \
}                        \
while (0)

pthread_mutex_t global_lock;
pthread_t global_threads[5];

void
setup_db ()
{ exec sql begin declare section;   const char *_user; exec sql end declare section;
 pthread_mutex_lock (&global_lock);
 _user = getenv ("LOGNAME");
 exec sql connect to :_user; CHECK_SQL ("connect");
 exec sql create table dbthreadtest (id int); CHECK_SQL ("create dbthreadtest");
 exec sql insert into dbthreadtest (id) values (1); CHECK_SQL ("insert 1");
 pthread_mutex_unlock (&global_lock);
}

void
teardown_db ()
{ pthread_mutex_lock (&global_lock);
 exec sql drop table dbthreadtest; CHECK_SQL ("drop dbthreadtest");
 exec sql disconnect; CHECK_SQL ("disconnect");
 pthread_mutex_unlock (&global_lock);
}

void *query_db (void *ignorep)
{ exec sql begin declare section;   int _id; exec sql end declare section;
 pthread_mutex_lock (&global_lock); exec sql select id into :_id from dbthreadtest; CHECK_SQL ("select id");
 fprintf (stdout, "got id = %d\n", _id); pthread_mutex_unlock (&global_lock);
 return NULL;
}

int
main ()
{ int i;
 pthread_mutex_init (&global_lock, NULL);  setup_db ();
 for (i = 0; i < sizeof (global_threads) / sizeof (global_threads[0]);
++i)   {     if (pthread_create (&global_threads[i], NULL, query_db, NULL))FATAL ("pthread_create %d failed", i);   }
 for (i = 0; i < sizeof (global_threads) / sizeof (global_threads[0]);
++i)   {     if (pthread_join (global_threads[i], NULL))FATAL ("pthread_join %d failed", i);   }
 teardown_db ();  return 0;
}

----- End forwarded message -----

-- 
Michael Meskes
Email: Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
ICQ: 179140304, AIM/Yahoo: michaelmeskes, Jabber: meskes@jabber.org
Go SF 49ers! Go Rhein Fire! Use Debian GNU/Linux! Use PostgreSQL!


Re: Need help woth thread support in ecpglib

From
Philip Yarra
Date:
Hi Michael, I'll have a look at it this afternoon, unless Lee wants first go.

Regards, Philip.

On Tuesday 12 April 2005 00:28, Michael Meskes wrote:
> Hi,
> 
> I recently got the following bug report. It appears to be a bug in
> pthread implementation in ecpglib/connect.c where 
> 
> pthread_getspecific(actual_connection_key);
> 
> doesn't return the value of actual_connection, the variable used for
> non-threaded mode. Problem is I never really used threading in my apps
> and didn't do the threading patches. Maybe someone with more knowledge
> than me could have a look at this. Thanks.
> 
> Michael
> 
> ---
> 
> When using postgresql 8.0 compiled with --enable-thread-safety, new threads
> no longer see the default ecpg connection.  That was not the case in 7.4.x
> compiled with or without --enable-thread-safety.
> 
> TEST CASE
> 
> The program at the end of this mail sets up a database table named
> "dbthreadtest" in the default database.  It then spawns 5 threads which each
> do a select from that table using the default connection.
> 
> If the program is saved as dbthreadtest.pgc, compile with:
> 
> ecpg -t -o dbthreadtest.c dbthreadtest.pgc
> gcc -Wall -o dbthreadtest dbthreadtest.c -lecpg -lpthread
> 
> Results under 7.4.x / 8.0 without --enable-thread-safety:
> 
> got id = 1
> got id = 1
> got id = 1
> got id = 1
> got id = 1
> 
> Results under 8.0 with --enable-thread-safety:
> 
> 'No such connection NULL in line 76.', sqlcode = -220 select id
> 
> TEST PROGRAM
> 
> /* -*-C-*- */
> 
> #include <stdlib.h>
> #include <pthread.h>
> 
> #define CHECK_SQL(fmt, args...)                \
> do                            \
> {                            \
>   if (sqlca.sqlcode != ECPG_NO_ERROR)            \
>     {                            \
>       fprintf (stderr, "'%s', sqlcode = %ld " fmt "\n",    \
>            sqlca.sqlerrm.sqlerrmc,            \
>            sqlca.sqlcode, ## args);            \
>       exit (1);                        \
>     }                            \
>  }                            \
> while (0)
> 
> #define FATAL(fmt, args...)            \
> do                        \
> {                        \
>   fprintf (stderr, fmt "\n", ## args);        \
>   exit (1);                    \
> }                        \
> while (0)
> 
> pthread_mutex_t global_lock;
> pthread_t global_threads[5];
> 
> void
> setup_db ()
> {
>   exec sql begin declare section;
>     const char *_user;
>   exec sql end declare section;
> 
>   pthread_mutex_lock (&global_lock);
> 
>   _user = getenv ("LOGNAME");
> 
>   exec sql connect to :_user;
>   CHECK_SQL ("connect");
> 
>   exec sql create table dbthreadtest (id int);
>   CHECK_SQL ("create dbthreadtest");
> 
>   exec sql insert into dbthreadtest (id) values (1);
>   CHECK_SQL ("insert 1");
> 
>   pthread_mutex_unlock (&global_lock);
> }
> 
> void
> teardown_db ()
> {
>   pthread_mutex_lock (&global_lock);
> 
>   exec sql drop table dbthreadtest;
>   CHECK_SQL ("drop dbthreadtest");
> 
>   exec sql disconnect;
>   CHECK_SQL ("disconnect");
> 
>   pthread_mutex_unlock (&global_lock);
> }
> 
> void *query_db (void *ignorep)
> {
>   exec sql begin declare section;
>     int _id;
>   exec sql end declare section;
> 
>   pthread_mutex_lock (&global_lock);
>   exec sql select id into :_id from dbthreadtest;
>   CHECK_SQL ("select id");
> 
>   fprintf (stdout, "got id = %d\n", _id);
>   pthread_mutex_unlock (&global_lock);
> 
>   return NULL;
> }
> 
> int
> main ()
> {
>   int i;
> 
>   pthread_mutex_init (&global_lock, NULL);
>   
>   setup_db ();
> 
>   for (i = 0; i < sizeof (global_threads) / sizeof (global_threads[0]);
> ++i)
>     {
>       if (pthread_create (&global_threads[i], NULL, query_db, NULL))
>     FATAL ("pthread_create %d failed", i);
>     }
> 
>   for (i = 0; i < sizeof (global_threads) / sizeof (global_threads[0]);
> ++i)
>     {
>       if (pthread_join (global_threads[i], NULL))
>     FATAL ("pthread_join %d failed", i);
>     }
> 
>   teardown_db ();
>   
>   return 0;
> }
> 
> ----- End forwarded message -----
> 
> -- 
> Michael Meskes
> Email: Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
> ICQ: 179140304, AIM/Yahoo: michaelmeskes, Jabber: meskes@jabber.org
> Go SF 49ers! Go Rhein Fire! Use Debian GNU/Linux! Use PostgreSQL!
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 8: explain analyze is your friend
> 
> -----------------
> Utiba Pty Ltd 
> This message has been scanned for viruses and
> dangerous content by Utiba mail server and is 
> believed to be clean.
> 
> 


-----------------
Utiba Pty Ltd 
This message has been scanned for viruses and
dangerous content by Utiba mail server and is 
believed to be clean.