diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index fa4ea4ddce691730d9e431845891ca09c57a6616..b7d33ff48ad2befff7509488224745cb9689de10 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -2242,5 +2242,10 @@ Mi 26. Sep 12:45:51 CEST 2007 - Applied patch by ITAGAKI Takahiro <itagaki.takahiro@oss.ntt.co.jp> to get prepare thread-safe. + +Sun, 30 Sep 2007 13:37:31 +0200 + + - Applied another patch by ITAGAKI Takahiro <itagaki.takahiro@oss.ntt.co.jp> + to get memory allocation thread-safe. He also did some cleaning up. - Set ecpg library version to 6.0. - Set ecpg version to 4.4. diff --git a/src/interfaces/ecpg/ecpglib/connect.c b/src/interfaces/ecpg/ecpglib/connect.c index 40f5d7ead3426621eff950015856bc6b16bf8e44..8d4146cfae3de8077b3aa222e8651e23348cc152 100644 --- a/src/interfaces/ecpg/ecpglib/connect.c +++ b/src/interfaces/ecpg/ecpglib/connect.c @@ -1,15 +1,9 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.43 2007/09/26 10:57:00 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.44 2007/09/30 11:38:48 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" -#ifdef ENABLE_THREAD_SAFETY -#ifndef WIN32 -#include <pthread.h> -#else #include "ecpg-pthread-win32.h" -#endif -#endif #include "ecpgtype.h" #include "ecpglib.h" #include "ecpgerrno.h" @@ -17,20 +11,17 @@ #include "sqlca.h" #ifdef ENABLE_THREAD_SAFETY +NON_EXEC_STATIC pthread_mutex_t connections_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_key_t actual_connection_key; #ifndef WIN32 -static pthread_mutex_t connections_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_key_t actual_connection_key; -static pthread_once_t actual_connection_key_once = PTHREAD_ONCE_INIT; -#else -static HANDLE connections_mutex = INVALID_HANDLE_VALUE; -static DWORD actual_connection_key; -#endif /* WIN32 */ +static pthread_once_t actual_connection_key_once = PTHREAD_ONCE_INIT; +#endif #endif static struct connection *actual_connection = NULL; static struct connection *all_connections = NULL; #ifdef ENABLE_THREAD_SAFETY -static void +NON_EXEC_STATIC void ecpg_actual_connection_init(void) { pthread_key_create(&actual_connection_key, NULL); @@ -39,13 +30,7 @@ ecpg_actual_connection_init(void) void ecpg_pthreads_init(void) { -#ifndef WIN32 pthread_once(&actual_connection_key_once, ecpg_actual_connection_init); -#else - static long has_run = 0; - if (InterlockedCompareExchange(&has_run, 1, 0) == 0) - ecpg_actual_connection_init(); -#endif } #endif @@ -134,6 +119,7 @@ ecpg_finish(struct connection * act) struct ECPGtype_information_cache *cache, *ptr; + ECPGdeallocate_all_conn(0, ECPG_COMPAT_PGSQL, act); PQfinish(act->connection); /* diff --git a/src/interfaces/ecpg/ecpglib/extern.h b/src/interfaces/ecpg/ecpglib/extern.h index f69730740be383620145f630fada0017ef30f73c..f7e91d3127059867790c58207c1556438996cefc 100644 --- a/src/interfaces/ecpg/ecpglib/extern.h +++ b/src/interfaces/ecpg/ecpglib/extern.h @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/extern.h,v 1.27 2007/09/26 10:57:00 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/extern.h,v 1.28 2007/09/30 11:38:48 meskes Exp $ */ #ifndef _ECPG_LIB_EXTERN_H #define _ECPG_LIB_EXTERN_H @@ -146,6 +146,7 @@ bool ECPGcheck_PQresult(PGresult *, int, PGconn *, enum COMPAT_MODE); void ECPGraise(int line, int code, const char *sqlstate, const char *str); void ECPGraise_backend(int line, PGresult *result, PGconn *conn, int compat); char *ECPGprepared(const char *, struct connection *, int); +bool ECPGdeallocate_all_conn(int lineno, enum COMPAT_MODE c, struct connection *conn); /* SQLSTATE values generated or processed by ecpglib (intentionally * not exported -- users should refer to the codes directly) */ diff --git a/src/interfaces/ecpg/ecpglib/memory.c b/src/interfaces/ecpg/ecpglib/memory.c index 3ee89a189a16e40b35c397613afaafcfa59ef9a5..0b3eb47d4e109b95b66f0d4e13fcaaf4554b24c6 100644 --- a/src/interfaces/ecpg/ecpglib/memory.c +++ b/src/interfaces/ecpg/ecpglib/memory.c @@ -1,8 +1,9 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/memory.c,v 1.8 2006/11/08 10:46:47 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/memory.c,v 1.9 2007/09/30 11:38:48 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" +#include "ecpg-pthread-win32.h" #include "ecpgtype.h" #include "ecpglib.h" #include "ecpgerrno.h" @@ -25,7 +26,6 @@ ECPGalloc(long size, int lineno) return NULL; } - memset(new, '\0', size); return (new); } @@ -62,11 +62,48 @@ ECPGstrdup(const char *string, int lineno) } /* keep a list of memory we allocated for the user */ -static struct auto_mem +struct auto_mem { void *pointer; struct auto_mem *next; -} *auto_allocs = NULL; +}; + +#ifdef ENABLE_THREAD_SAFETY +static pthread_key_t auto_mem_key; +#ifndef WIN32 +static pthread_once_t auto_mem_once = PTHREAD_ONCE_INIT; +#endif + +static void +auto_mem_destructor(void *arg) +{ + ECPGfree_auto_mem(); +} + +NON_EXEC_STATIC void +auto_mem_key_init(void) +{ + pthread_key_create(&auto_mem_key, auto_mem_destructor); +} + +static struct auto_mem * +get_auto_allocs(void) +{ + pthread_once(&auto_mem_once, auto_mem_key_init); + return (struct auto_mem *) pthread_getspecific(auto_mem_key); +} + +static void +set_auto_allocs(struct auto_mem *am) +{ + pthread_setspecific(auto_mem_key, am); +} + +#else +static struct auto_mem *auto_allocs = NULL; +#define get_auto_allocs() (auto_allocs) +#define set_auto_allocs(am) do { auto_allocs = (am); } while(0) +#endif void ECPGadd_mem(void *ptr, int lineno) @@ -74,41 +111,43 @@ ECPGadd_mem(void *ptr, int lineno) struct auto_mem *am = (struct auto_mem *) ECPGalloc(sizeof(struct auto_mem), lineno); am->pointer = ptr; - am->next = auto_allocs; - auto_allocs = am; + am->next = get_auto_allocs(); + set_auto_allocs(am); } void ECPGfree_auto_mem(void) { - struct auto_mem *am; + struct auto_mem *am = get_auto_allocs(); /* free all memory we have allocated for the user */ - for (am = auto_allocs; am;) + if (am) { - struct auto_mem *act = am; - - am = am->next; - ECPGfree(act->pointer); - ECPGfree(act); + do + { + struct auto_mem *act = am; + am = am->next; + ECPGfree(act->pointer); + ECPGfree(act); + } while(am); + set_auto_allocs(NULL); } - - auto_allocs = NULL; } void ECPGclear_auto_mem(void) { - struct auto_mem *am; + struct auto_mem *am = get_auto_allocs(); /* only free our own structure */ - for (am = auto_allocs; am;) + if (am) { - struct auto_mem *act = am; - - am = am->next; - ECPGfree(act); + do + { + struct auto_mem *act = am; + am = am->next; + ECPGfree(act); + } while(am); + set_auto_allocs(NULL); } - - auto_allocs = NULL; } diff --git a/src/interfaces/ecpg/ecpglib/misc.c b/src/interfaces/ecpg/ecpglib/misc.c index 1da37ec5f77894f1a627ed3abbaf9ad27ab3d87b..4dfa8cab542e1b4ab290579d4c0e183b4683a879 100644 --- a/src/interfaces/ecpg/ecpglib/misc.c +++ b/src/interfaces/ecpg/ecpglib/misc.c @@ -1,17 +1,11 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.36 2007/08/14 10:01:52 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.37 2007/09/30 11:38:48 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" #include <limits.h> #include <unistd.h> -#ifdef ENABLE_THREAD_SAFETY -#ifndef WIN32 -#include <pthread.h> -#else #include "ecpg-pthread-win32.h" -#endif -#endif #include "ecpgtype.h" #include "ecpglib.h" #include "ecpgerrno.h" @@ -62,11 +56,9 @@ static struct sqlca_t sqlca_init = }; #ifdef ENABLE_THREAD_SAFETY -#ifndef WIN32 static pthread_key_t sqlca_key; +#ifndef WIN32 static pthread_once_t sqlca_key_once = PTHREAD_ONCE_INIT; -#else -static DWORD sqlca_key; #endif #else static struct sqlca_t sqlca = @@ -98,13 +90,8 @@ static struct sqlca_t sqlca = #endif #ifdef ENABLE_THREAD_SAFETY -#ifndef WIN32 -static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t debug_init_mutex = PTHREAD_MUTEX_INITIALIZER; -#else -static HANDLE debug_mutex = INVALID_HANDLE_VALUE; -static HANDLE debug_init_mutex = INVALID_HANDLE_VALUE; -#endif /* WIN32 */ +NON_EXEC_STATIC pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER; +NON_EXEC_STATIC pthread_mutex_t debug_init_mutex = PTHREAD_MUTEX_INITIALIZER; #endif static int simple_debug = 0; static FILE *debugstream = NULL; @@ -135,11 +122,10 @@ ECPGinit(const struct connection * con, const char *connection_name, const int l static void ecpg_sqlca_key_destructor(void *arg) { - if (arg != NULL) - free(arg); /* sqlca structure allocated in ECPGget_sqlca */ + free(arg); /* sqlca structure allocated in ECPGget_sqlca */ } -static void +NON_EXEC_STATIC void ecpg_sqlca_key_init(void) { pthread_key_create(&sqlca_key, ecpg_sqlca_key_destructor); @@ -151,13 +137,8 @@ ECPGget_sqlca(void) { #ifdef ENABLE_THREAD_SAFETY struct sqlca_t *sqlca; -#ifdef WIN32 - static long has_run = 0; - if (InterlockedCompareExchange(&has_run, 1, 0) == 0) - ecpg_sqlca_key_init(); -#else + pthread_once(&sqlca_key_once, ecpg_sqlca_key_init); -#endif sqlca = pthread_getspecific(sqlca_key); if (sqlca == NULL) @@ -263,22 +244,13 @@ ECPGlog(const char *format,...) va_list ap; struct sqlca_t *sqlca = ECPGget_sqlca(); -#ifdef ENABLE_THREAD_SAFETY - pthread_mutex_lock(&debug_mutex); -#endif - if (simple_debug) { int bufsize = strlen(format) + 100; char *f = (char *) malloc(bufsize); if (f == NULL) - { -#ifdef ENABLE_THREAD_SAFETY - pthread_mutex_unlock(&debug_mutex); -#endif return; - } /* * regression tests set this environment variable to get the same @@ -289,6 +261,10 @@ ECPGlog(const char *format,...) else snprintf(f, bufsize, "[%d]: %s", (int) getpid(), format); +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_lock(&debug_mutex); +#endif + va_start(ap, format); vfprintf(debugstream, f, ap); va_end(ap); @@ -300,12 +276,12 @@ ECPGlog(const char *format,...) fflush(debugstream); - ECPGfree(f); - } - #ifdef ENABLE_THREAD_SAFETY - pthread_mutex_unlock(&debug_mutex); + pthread_mutex_unlock(&debug_mutex); #endif + + free(f); + } } void @@ -437,3 +413,25 @@ ECPGis_noind_null(enum ECPGttype type, void *ptr) return false; } + +#ifdef WIN32 + +/* + * Initialize mutexes and call init-once functions on loading. + */ + +BOOL WINAPI +DllMain(HANDLE module, DWORD reason, LPVOID reserved) +{ + if (reason == DLL_PROCESS_ATTACH) + { + connections_mutex = CreateMutex(NULL, FALSE, NULL); + debug_mutex = CreateMutex(NULL, FALSE, NULL); + debug_init_mutex = CreateMutex(NULL, FALSE, NULL); + auto_mem_key_init(); + ecpg_actual_connection_init(); + ecpg_sqlca_key_init(); + } + return TRUE; +} +#endif diff --git a/src/interfaces/ecpg/ecpglib/prepare.c b/src/interfaces/ecpg/ecpglib/prepare.c index 6d884bfb0ae864909840d532b30643853d0c3c33..1afa63c9339be935e79c85590202b95ada0d6499 100644 --- a/src/interfaces/ecpg/ecpglib/prepare.c +++ b/src/interfaces/ecpg/ecpglib/prepare.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.20 2007/09/26 10:57:00 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.21 2007/09/30 11:38:48 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" @@ -31,8 +31,8 @@ typedef struct } stmtCacheEntry; static int nextStmtID = 1; -static int stmtCacheNBuckets = 2039; /* # buckets - a prime # */ -static int stmtCacheEntPerBucket = 8; /* # entries/bucket */ +const static int stmtCacheNBuckets = 2039; /* # buckets - a prime # */ +const static int stmtCacheEntPerBucket = 8; /* # entries/bucket */ static stmtCacheEntry stmtCacheEntries[16384] = {{0,{0},0,0,0}}; static struct prepared_statement *find_prepared_statement(const char *name, @@ -263,22 +263,24 @@ ECPGdeallocate(int lineno, int c, const char *connection_name, const char *name) } bool -ECPGdeallocate_all(int lineno, int compat, const char *connection_name) +ECPGdeallocate_all_conn(int lineno, enum COMPAT_MODE c, struct connection *con) { - struct connection *con; - - con = ECPGget_connection(connection_name); - /* deallocate all prepared statements */ while (con->prep_stmts) { - if (!deallocate_one(lineno, compat, con, NULL, con->prep_stmts)) + if (!deallocate_one(lineno, c, con, NULL, con->prep_stmts)) return false; } return true; } +bool +ECPGdeallocate_all(int lineno, int compat, const char *connection_name) +{ + return ECPGdeallocate_all_conn(lineno, compat, ECPGget_connection(connection_name)); +} + char * ECPGprepared(const char *name, struct connection *con, int lineno) { diff --git a/src/interfaces/ecpg/include/ecpg-pthread-win32.h b/src/interfaces/ecpg/include/ecpg-pthread-win32.h index df076ac8e595e2ac877f0e292371eaa457a2a79f..e0bbc93f39fe91b05e30003f3222caeb87b923d6 100644 --- a/src/interfaces/ecpg/include/ecpg-pthread-win32.h +++ b/src/interfaces/ecpg/include/ecpg-pthread-win32.h @@ -1,16 +1,56 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/include/ecpg-pthread-win32.h,v 1.1 2007/03/29 12:02:24 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/include/ecpg-pthread-win32.h,v 1.2 2007/09/30 11:38:48 meskes Exp $ */ /* * pthread mapping macros for win32 native thread implementation */ #ifndef _ECPG_PTHREAD_WIN32_H #define _ECPG_PTHREAD_WIN32_H -#define pthread_mutex_lock(x) do { \ - if (*x == INVALID_HANDLE_VALUE) \ - *x = CreateMutex(NULL, FALSE, NULL); \ - WaitForSingleObject(*x, INFINITE); \ -} while (0); -#define pthread_mutex_unlock(x) ReleaseMutex(*x) -#define pthread_getspecific(x) TlsGetValue(x) -#define pthread_setspecific(x,y) TlsSetValue(x,y) -#define pthread_key_create(x,y) *x = TlsAlloc(); -#endif + +#ifdef ENABLE_THREAD_SAFETY + +#ifndef WIN32 + +#include <pthread.h> +#define NON_EXEC_STATIC static + +#else + +#define NON_EXEC_STATIC + +typedef HANDLE pthread_mutex_t; +typedef DWORD pthread_key_t; + +#define PTHREAD_MUTEX_INITIALIZER INVALID_HANDLE_VALUE + +#define pthread_mutex_lock(mutex) \ + WaitForSingleObject(*(mutex), INFINITE); + +#define pthread_mutex_unlock(mutex) \ + ReleaseMutex(*(mutex)) + +#define pthread_getspecific(key) \ + TlsGetValue((key)) + +#define pthread_setspecific(key, value) \ + TlsSetValue((key), (value)) + +/* FIXME: destructor is never called in Win32. */ +#define pthread_key_create(key, destructor) \ + do { *(key) = TlsAlloc(); ((void)(destructor)); } while(0) + +/* init-once functions are always called when libecpg is loaded */ +#define pthread_once(key, fn) \ + ((void)0) + +extern pthread_mutex_t connections_mutex; +extern pthread_mutex_t debug_mutex; +extern pthread_mutex_t debug_init_mutex; +extern void auto_mem_key_init(void); +extern void ecpg_actual_connection_init(void); +extern void ecpg_sqlca_key_init(void); +extern BOOL WINAPI DllMain(HANDLE module, DWORD reason, LPVOID reserved); + +#endif /* WIN32 */ + +#endif /* ENABLE_THREAD_SAFETY */ + +#endif /* _ECPG_PTHREAD_WIN32_H */ diff --git a/src/interfaces/ecpg/pgtypeslib/dt_common.c b/src/interfaces/ecpg/pgtypeslib/dt_common.c index 299186ec02a23431e78527d682c5fe792c289432..212ca0eebb6fd789b784e8a581528c2b117e7b53 100644 --- a/src/interfaces/ecpg/pgtypeslib/dt_common.c +++ b/src/interfaces/ecpg/pgtypeslib/dt_common.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt_common.c,v 1.42 2007/08/22 08:20:58 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt_common.c,v 1.43 2007/09/30 11:38:48 meskes Exp $ */ #include "postgres_fe.h" @@ -496,8 +496,8 @@ static datetkn deltatktbl[] = { {"yrs", UNITS, DTK_YEAR}, /* "years" relative */ }; -static unsigned int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0]; -static unsigned int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0]; +static const unsigned int szdatetktbl = lengthof(datetktbl); +static const unsigned int szdeltatktbl = lengthof(deltatktbl); static datetkn *datecache[MAXDATEFIELDS] = {NULL}; diff --git a/src/interfaces/ecpg/test/ecpg_schedule b/src/interfaces/ecpg/test/ecpg_schedule index 432a458cdef85230591d2daaa37de112a5d38feb..6067db2666427674a1f3ec149d75330d0585aed7 100644 --- a/src/interfaces/ecpg/test/ecpg_schedule +++ b/src/interfaces/ecpg/test/ecpg_schedule @@ -42,3 +42,4 @@ test: sql/parser test: thread/thread test: thread/thread_implicit test: thread/prep +test: thread/alloc diff --git a/src/interfaces/ecpg/test/ecpg_schedule_tcp b/src/interfaces/ecpg/test/ecpg_schedule_tcp index 64fbca21179033fb2acd2f84afeb8e75c21c4bc0..20e322bbde349d02bfd220f1ee715911b4f37ea3 100644 --- a/src/interfaces/ecpg/test/ecpg_schedule_tcp +++ b/src/interfaces/ecpg/test/ecpg_schedule_tcp @@ -42,5 +42,6 @@ test: sql/parser test: thread/thread test: thread/thread_implicit test: thread/prep +test: thread/alloc test: connect/test1 diff --git a/src/interfaces/ecpg/test/expected/preproc-autoprep.stderr b/src/interfaces/ecpg/test/expected/preproc-autoprep.stderr index ec86193d9d16fc1956b10e75df79c5118ea21e50..68d7ff659cfe4c584aa3f3aca246037f30db342a 100644 --- a/src/interfaces/ecpg/test/expected/preproc-autoprep.stderr +++ b/src/interfaces/ecpg/test/expected/preproc-autoprep.stderr @@ -112,5 +112,23 @@ [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ECPGexecute line 42 Ok: DROP TABLE [NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGdeallocate line 0: NAME: ecpg8 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGdeallocate line 0: NAME: ecpg7 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGdeallocate line 0: NAME: ecpg6 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGdeallocate line 0: NAME: ecpg5 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGdeallocate line 0: NAME: ecpg4 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGdeallocate line 0: NAME: i +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGdeallocate line 0: NAME: ecpg3 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGdeallocate line 0: NAME: ecpg2 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGdeallocate line 0: NAME: ecpg1 +[NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: Connection regress1 closed. [NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/expected/sql-execute.stderr b/src/interfaces/ecpg/test/expected/sql-execute.stderr index d6c76a9b8a96cd1f1bf1c25e7d3bc28fe2e55e6e..d9fbbc3497d1b87bdc65d5b23c30a577535808c8 100644 --- a/src/interfaces/ecpg/test/expected/sql-execute.stderr +++ b/src/interfaces/ecpg/test/expected/sql-execute.stderr @@ -146,5 +146,9 @@ [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ECPGtrans line 90 action = commit connection = main [NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGdeallocate line 0: NAME: f +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGdeallocate line 0: NAME: i +[NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: Connection main closed. [NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/expected/sql-oldexec.stderr b/src/interfaces/ecpg/test/expected/sql-oldexec.stderr index 66f181d51154dc3c8769406493f1318b2a0e994a..c1f85b0b63f128ddc90e55ae68aa1d1b58683a22 100644 --- a/src/interfaces/ecpg/test/expected/sql-oldexec.stderr +++ b/src/interfaces/ecpg/test/expected/sql-oldexec.stderr @@ -146,5 +146,9 @@ [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ECPGtrans line 89 action = commit connection = main [NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGdeallocate line 0: NAME: f +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGdeallocate line 0: NAME: i +[NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: Connection main closed. [NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/expected/thread-alloc.c b/src/interfaces/ecpg/test/expected/thread-alloc.c new file mode 100644 index 0000000000000000000000000000000000000000..12a95df8f668af321fcbbe900618f3fbb56a7c75 --- /dev/null +++ b/src/interfaces/ecpg/test/expected/thread-alloc.c @@ -0,0 +1,218 @@ +/* Processed by ecpg (regression mode) */ +/* These include files are added by the preprocessor */ +#include <ecpgtype.h> +#include <ecpglib.h> +#include <ecpgerrno.h> +#include <sqlca.h> +/* End of automatic include section */ +#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y)) + +#line 1 "alloc.pgc" +#include <stdlib.h> +#include "ecpg_config.h" + +#ifndef ENABLE_THREAD_SAFETY +int +main(void) +{ + printf("No threading enabled.\n"); + return 0; +} +#else +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <process.h> +#else +#include <pthread.h> +#endif +#include <stdio.h> + +#define THREADS 16 +#define REPEATS 50 + + +#line 1 "sqlca.h" +#ifndef POSTGRES_SQLCA_H +#define POSTGRES_SQLCA_H + +#ifndef PGDLLIMPORT +#if defined(WIN32) || defined(__CYGWIN__) +#define PGDLLIMPORT __declspec (dllimport) +#else +#define PGDLLIMPORT +#endif /* __CYGWIN__ */ +#endif /* PGDLLIMPORT */ + +#define SQLERRMC_LEN 150 + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct sqlca_t +{ + char sqlcaid[8]; + long sqlabc; + long sqlcode; + struct + { + int sqlerrml; + char sqlerrmc[SQLERRMC_LEN]; + } sqlerrm; + char sqlerrp[8]; + long sqlerrd[6]; + /* Element 0: empty */ + /* 1: OID of processed tuple if applicable */ + /* 2: number of rows processed */ + /* after an INSERT, UPDATE or */ + /* DELETE statement */ + /* 3: empty */ + /* 4: empty */ + /* 5: empty */ + char sqlwarn[8]; + /* Element 0: set to 'W' if at least one other is 'W' */ + /* 1: if 'W' at least one character string */ + /* value was truncated when it was */ + /* stored into a host variable. */ + + /* + * 2: if 'W' a (hopefully) non-fatal notice occurred + */ /* 3: empty */ + /* 4: empty */ + /* 5: empty */ + /* 6: empty */ + /* 7: empty */ + + char sqlstate[5]; +}; + +struct sqlca_t *ECPGget_sqlca(void); + +#ifndef POSTGRES_ECPG_INTERNAL +#define sqlca (*ECPGget_sqlca()) +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#line 24 "alloc.pgc" + + +#line 1 "regression.h" + + + + + + +#line 25 "alloc.pgc" + + +/* exec sql whenever sqlerror sqlprint ; */ +#line 27 "alloc.pgc" + +/* exec sql whenever not found sqlprint ; */ +#line 28 "alloc.pgc" + + +#ifdef WIN32 +static unsigned STDCALL fn(void* arg) +#else +static void* fn(void* arg) +#endif +{ + int i; + + /* exec sql begin declare section */ + + + + +#line 39 "alloc.pgc" + int value ; + +#line 40 "alloc.pgc" + char name [ 100 ] ; + +#line 41 "alloc.pgc" + char ** r = NULL ; +/* exec sql end declare section */ +#line 42 "alloc.pgc" + + + value = (int)arg; + sprintf(name, "Connection: %d", value); + + { ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , name, 0); +#line 47 "alloc.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 47 "alloc.pgc" + + { ECPGsetcommit(__LINE__, "on", NULL); +#line 48 "alloc.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 48 "alloc.pgc" + + for (i = 1; i <= REPEATS; ++i) + { + { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select relname from pg_class where relname = 'pg_class' ", ECPGt_EOIT, + ECPGt_char,&(r),(long)0,(long)0,(1)*sizeof(char), + ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); +#line 51 "alloc.pgc" + +if (sqlca.sqlcode == ECPG_NOT_FOUND) sqlprint(); +#line 51 "alloc.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 51 "alloc.pgc" + + free(r); + r = NULL; + } + { ECPGdisconnect(__LINE__, name); +#line 55 "alloc.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 55 "alloc.pgc" + + + return 0; +} + +int main (int argc, char** argv) +{ + int i; +#ifdef WIN32 + HANDLE threads[THREADS]; +#else + pthread_t threads[THREADS]; +#endif + +#ifdef WIN32 + for (i = 0; i < THREADS; ++i) + { + unsigned id; + threads[i] = (HANDLE)_beginthreadex(NULL, 0, fn, (void*)i, 0, &id); + } + + WaitForMultipleObjects(THREADS, threads, TRUE, INFINITE); + for (i = 0; i < THREADS; ++i) + CloseHandle(threads[i]); +#else + for (i = 0; i < THREADS; ++i) + pthread_create(&threads[i], NULL, fn, (void*)i); + for (i = 0; i < THREADS; ++i) + pthread_join(threads[i], NULL); +#endif + + return 0; +} +#endif + diff --git a/src/interfaces/ecpg/test/expected/thread-alloc.stderr b/src/interfaces/ecpg/test/expected/thread-alloc.stderr new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/interfaces/ecpg/test/expected/thread-alloc.stdout b/src/interfaces/ecpg/test/expected/thread-alloc.stdout new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/interfaces/ecpg/test/expected/thread-alloc_2.stdout b/src/interfaces/ecpg/test/expected/thread-alloc_2.stdout new file mode 100644 index 0000000000000000000000000000000000000000..75fe16bb36bb2580d8365d62780f9c21ad7c259c --- /dev/null +++ b/src/interfaces/ecpg/test/expected/thread-alloc_2.stdout @@ -0,0 +1 @@ +No threading enabled. diff --git a/src/interfaces/ecpg/test/expected/thread-prep.c b/src/interfaces/ecpg/test/expected/thread-prep.c index cc3129b6c9c3ce98b343d550167de5bed4685a58..22b63f16fceeee09695dda11606c29348eff75ad 100644 --- a/src/interfaces/ecpg/test/expected/thread-prep.c +++ b/src/interfaces/ecpg/test/expected/thread-prep.c @@ -15,7 +15,7 @@ int main(void) { - printf("No threading enabled.\n"); + printf("No threading enabled.\n"); return 0; } #else @@ -123,7 +123,7 @@ struct sqlca_t *ECPGget_sqlca(void); #ifdef WIN32 static unsigned STDCALL fn(void* arg) #else -void* fn(void* arg) +static void* fn(void* arg) #endif { int i; diff --git a/src/interfaces/ecpg/test/thread/Makefile b/src/interfaces/ecpg/test/thread/Makefile index 8695a254ac1ee58517ecdbc5b54462198c791101..e4df0d3cdad3279a51b39f91f6e15a62b187380e 100644 --- a/src/interfaces/ecpg/test/thread/Makefile +++ b/src/interfaces/ecpg/test/thread/Makefile @@ -6,7 +6,8 @@ include $(top_srcdir)/$(subdir)/../Makefile.regress TESTS = thread_implicit thread_implicit.c \ thread thread.c \ - prep prep.c + prep prep.c \ + alloc alloc.c all: $(TESTS) diff --git a/src/interfaces/ecpg/test/thread/prep.pgc b/src/interfaces/ecpg/test/thread/prep.pgc index 1213975b1636933fe7fd7e3c0fccd0eb42816ae5..314e24eecd25c88f05737c30037b215f6e220eed 100644 --- a/src/interfaces/ecpg/test/thread/prep.pgc +++ b/src/interfaces/ecpg/test/thread/prep.pgc @@ -5,7 +5,7 @@ int main(void) { - printf("No threading enabled.\n"); + printf("No threading enabled.\n"); return 0; } #else @@ -30,7 +30,7 @@ exec sql whenever not found sqlprint; #ifdef WIN32 static unsigned STDCALL fn(void* arg) #else -void* fn(void* arg) +static void* fn(void* arg) #endif { int i;