Need help woth thread support in ecpglib

Started by Michael Meskesalmost 21 years ago2 messages
#1Michael Meskes
meskes@postgresql.org

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!

#2Philip Yarra
philip@utiba.com
In reply to: Michael Meskes (#1)
Re: Need help woth thread support in ecpglib

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.