From db0db11147deb5767cccb46820401c2754a7ed16 Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Mon, 12 Dec 2011 20:46:20 +0000 Subject: Split cci_thread_init into per-process and per-thread portions Call the per-thread code on thread attach and per-process once per process. Previously, while the function was named 'thread', it was only actually called once per process. Currently, the per-thread code does nothing on non-windows platforms and is not even actually invoked. Fixes a windows bug when multiple non-main threads try to use ccapi at the same time. Signed-off-by: Kevin Wasserman ticket: 7050 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25569 dc483132-0cff-0310-8789-dd5450dbe970 --- src/ccapi/common/win/OldCC/autolock.hxx | 11 ++- src/ccapi/lib/ccapi_context.c | 14 ++-- src/ccapi/lib/ccapi_ipc.c | 7 ++ src/ccapi/lib/ccapi_ipc.h | 2 + src/ccapi/lib/ccapi_os_ipc.h | 2 + src/ccapi/lib/win/OldCC/client.cxx | 5 +- src/ccapi/lib/win/ccapi_os_ipc.cxx | 120 +++++++++++++++++--------------- src/ccapi/lib/win/debug.exports | 1 + src/ccapi/lib/win/dllmain.cxx | 11 ++- 9 files changed, 101 insertions(+), 72 deletions(-) (limited to 'src/ccapi') diff --git a/src/ccapi/common/win/OldCC/autolock.hxx b/src/ccapi/common/win/OldCC/autolock.hxx index bbd773488c..45b881e221 100644 --- a/src/ccapi/common/win/OldCC/autolock.hxx +++ b/src/ccapi/common/win/OldCC/autolock.hxx @@ -35,10 +35,8 @@ public: ~CcOsLock() {DeleteCriticalSection(&cs); valid = false;} void lock() {if (valid) EnterCriticalSection(&cs);} void unlock() {if (valid) LeaveCriticalSection(&cs);} -#if 0 bool trylock() {return valid ? (TryEnterCriticalSection(&cs) ? true : false) : false; } -#endif }; class CcAutoLock { @@ -50,4 +48,13 @@ public: ~CcAutoLock() { m_lock.unlock(); } }; +class CcAutoTryLock { + CcOsLock& m_lock; + bool m_locked; +public: + CcAutoTryLock(CcOsLock& lock):m_lock(lock) { m_locked = m_lock.trylock(); } + ~CcAutoTryLock() { if (m_locked) m_lock.unlock(); m_locked = false; } + bool IsLocked() const { return m_locked; } +}; + #endif /* __AUTOLOCK_HXX */ diff --git a/src/ccapi/lib/ccapi_context.c b/src/ccapi/lib/ccapi_context.c index a16ce0e580..cf677fc551 100644 --- a/src/ccapi/lib/ccapi_context.c +++ b/src/ccapi/lib/ccapi_context.c @@ -79,12 +79,12 @@ static cc_int32 cci_context_sync (cci_context_t in_context, #pragma mark - #endif -MAKE_INIT_FUNCTION(cci_thread_init); -MAKE_FINI_FUNCTION(cci_thread_fini); +MAKE_INIT_FUNCTION(cci_process_init); +MAKE_FINI_FUNCTION(cci_process_fini); /* ------------------------------------------------------------------------ */ -static int cci_thread_init (void) +static int cci_process_init (void) { cc_int32 err = ccNoError; @@ -93,7 +93,7 @@ static int cci_thread_init (void) } if (!err) { - err = cci_ipc_thread_init (); + err = cci_ipc_process_init (); } if (!err) { @@ -105,9 +105,9 @@ static int cci_thread_init (void) /* ------------------------------------------------------------------------ */ -static void cci_thread_fini (void) +static void cci_process_fini (void) { - if (!INITIALIZER_RAN (cci_thread_init) || PROGRAM_EXITING ()) { + if (!INITIALIZER_RAN (cci_process_init) || PROGRAM_EXITING ()) { return; } @@ -134,7 +134,7 @@ cc_int32 cc_initialize (cc_context_t *out_context, if (!out_context) { err = cci_check_error (ccErrBadParam); } if (!err) { - err = CALL_INIT_FUNCTION (cci_thread_init); + err = CALL_INIT_FUNCTION (cci_process_init); } if (!err) { diff --git a/src/ccapi/lib/ccapi_ipc.c b/src/ccapi/lib/ccapi_ipc.c index 66830de8eb..2c1fcba610 100644 --- a/src/ccapi/lib/ccapi_ipc.c +++ b/src/ccapi/lib/ccapi_ipc.c @@ -28,6 +28,13 @@ /* ------------------------------------------------------------------------ */ +cc_int32 cci_ipc_process_init (void) +{ + return cci_os_ipc_process_init (); +} + +/* ------------------------------------------------------------------------ */ + cc_int32 cci_ipc_thread_init (void) { return cci_os_ipc_thread_init (); diff --git a/src/ccapi/lib/ccapi_ipc.h b/src/ccapi/lib/ccapi_ipc.h index a23791cf46..a23772b29f 100644 --- a/src/ccapi/lib/ccapi_ipc.h +++ b/src/ccapi/lib/ccapi_ipc.h @@ -28,6 +28,8 @@ #include "cci_common.h" +cc_int32 cci_ipc_process_init (void); + cc_int32 cci_ipc_thread_init (void); cc_int32 cci_ipc_send (enum cci_msg_id_t in_request_name, diff --git a/src/ccapi/lib/ccapi_os_ipc.h b/src/ccapi/lib/ccapi_os_ipc.h index e27ae63c24..fe7c87a08c 100644 --- a/src/ccapi/lib/ccapi_os_ipc.h +++ b/src/ccapi/lib/ccapi_os_ipc.h @@ -28,6 +28,8 @@ #include "cci_common.h" +cc_int32 cci_os_ipc_process_init (void); + cc_int32 cci_os_ipc_thread_init (void); cc_int32 cci_os_ipc (cc_int32 in_launch_server, diff --git a/src/ccapi/lib/win/OldCC/client.cxx b/src/ccapi/lib/win/OldCC/client.cxx index 5a34d38cc5..4b2d718cc4 100644 --- a/src/ccapi/lib/win/OldCC/client.cxx +++ b/src/ccapi/lib/win/OldCC/client.cxx @@ -395,10 +395,11 @@ Client::Connect(char* ep OPTIONAL) { } DWORD Client::Initialize(char* ep OPTIONAL) { - CcAutoLock AL(Client::sLock); + CcAutoTryLock AL(Client::sLock); + if (!AL.IsLocked() || s_init) + return 0; SecureClient s; ccs_request_IfHandle = NULL; - if (s_init) return 0; DWORD status = Client::Connect(ep); if (!status) s_init = true; return status; diff --git a/src/ccapi/lib/win/ccapi_os_ipc.cxx b/src/ccapi/lib/win/ccapi_os_ipc.cxx index 7359eb0bad..8cc9d03bd4 100644 --- a/src/ccapi/lib/win/ccapi_os_ipc.cxx +++ b/src/ccapi/lib/win/ccapi_os_ipc.cxx @@ -64,7 +64,7 @@ SECURITY_ATTRIBUTES sa = { 0 }; */ cc_int32 ccapi_connect(const struct tspdata* tsp); -static DWORD handle_exception(DWORD code); +static DWORD handle_exception(DWORD code, struct tspdata* ptspdata); extern "C" { cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, @@ -75,12 +75,46 @@ cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, /* ------------------------------------------------------------------------ */ +extern "C" cc_int32 cci_os_ipc_process_init (void) { + RPC_STATUS status; + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + if (!isNT()) { + status = RpcServerRegisterIf(ccs_reply_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL); // MgrEpv; null means use default + } + else { + status = RpcServerRegisterIfEx(ccs_reply_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL, // MgrEpv; 0 means default + RPC_IF_ALLOW_SECURE_ONLY, + opts.cMaxCalls, + NULL); // No security callback. + } + cci_check_error(status); + + if (!status) { + status = RpcServerRegisterAuthInfo(0, // server principal + RPC_C_AUTHN_WINNT, + 0, + 0 ); + cci_check_error(status); + } + + return status; // ugh. needs translation +} + +/* ------------------------------------------------------------------------ */ + extern "C" cc_int32 cci_os_ipc_thread_init (void) { cc_int32 err = ccNoError; struct tspdata* ptspdata; - HANDLE replyEvent; + HANDLE replyEvent = NULL; UUID __RPC_FAR uuid; - unsigned char __RPC_FAR* uuidString = NULL; + RPC_CSTR __RPC_FAR uuidString = NULL; + char* endpoint = NULL; if (!GetTspData(GetTlsIndex(), &ptspdata)) return ccErrNoMem; @@ -91,10 +125,18 @@ extern "C" cc_int32 cci_os_ipc_thread_init (void) { err = cci_check_error(UuidCreate(&uuid)); // Get a UUID if (err == RPC_S_OK) { // Convert to string err = UuidToString(&uuid, &uuidString); + cci_check_error(err); } if (!err) { // Save in thread local storage tspdata_setUUID(ptspdata, uuidString); + endpoint = clientEndpoint((const char *)uuidString); + err = RpcServerUseProtseqEp((RPC_CSTR)"ncalrpc", + opts.cMaxCalls, + (RPC_CSTR)endpoint, + sa.lpSecurityDescriptor); // SD + cci_check_error(err); } + #if 0 cci_debug_printf("%s UUID:<%s>", __FUNCTION__, tspdata_getUUID(ptspdata)); #endif @@ -109,6 +151,17 @@ extern "C" cc_int32 cci_os_ipc_thread_init (void) { replyEvent = createThreadEvent((char*)uuidString, REPLY_SUFFIX); } + if (!err) { + static bool bListening = false; + if (!bListening) { + err = RpcServerListen(opts.cMinCalls, + opts.cMaxCalls, + TRUE); + cci_check_error(err); + } + bListening = err == 0; + } + if (replyEvent) tspdata_setReplyEvent(ptspdata, replyEvent); else err = cci_check_error(GetLastError()); @@ -159,6 +212,10 @@ extern "C" cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, sst = tspdata_getSST (ptspdata); uuid = tspdata_getUUID(ptspdata); + // Initialize old CCAPI if necessary: + if (!err) if (!Init:: Initialized()) err = cci_check_error(Init:: Initialize( )); + if (!err) if (!Client::Initialized()) err = cci_check_error(Client::Initialize(0)); + // The lazy connection to the server has been put off as long as possible! // ccapi_connect starts listening for replies as an RPC server and then // calls ccs_rpc_connect. @@ -183,10 +240,6 @@ extern "C" cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, CcAutoLock* a = 0; CcAutoLock::Start(a, Client::sLock); - // Initialize old CCAPI if necessary: - if (!err) if (!Init:: Initialized()) err = cci_check_error(Init:: Initialize( )); - if (!err) if (!Client::Initialized()) err = cci_check_error(Client::Initialize(0)); - // New code using new RPC procedures for sending the data and receiving a reply: if (!err) { RpcTryExcept { @@ -209,7 +262,7 @@ extern "C" cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, (long*)(&err) ); /* Return code */ } RpcExcept(1) { - handle_exception(RpcExceptionCode()); + err = handle_exception(RpcExceptionCode(), ptspdata); } RpcEndExcept; } @@ -247,12 +300,13 @@ extern "C" cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, -static DWORD handle_exception(DWORD code) { +static DWORD handle_exception(DWORD code, struct tspdata* ptspdata) { cci_debug_printf("%s code %u; ccs_request_IfHandle:0x%X", __FUNCTION__, code, ccs_request_IfHandle); if ( (code == RPC_S_SERVER_UNAVAILABLE) || (code == RPC_S_INVALID_BINDING) ) { - Client::Reconnect(0); + Client::Cleanup(); + tspdata_setConnected(ptspdata, FALSE); } - return 4; + return code; } @@ -262,7 +316,6 @@ static DWORD handle_exception(DWORD code) { */ cc_int32 ccapi_connect(const struct tspdata* tsp) { BOOL bListen = TRUE; - char* endpoint = NULL; HANDLE replyEvent = 0; RPC_STATUS status = FALSE; char* uuid = NULL; @@ -275,56 +328,13 @@ cc_int32 ccapi_connect(const struct tspdata* tsp) { /* Build complete RPC uuid using previous CCAPI implementation: */ replyEvent = tspdata_getReplyEvent(tsp); uuid = tspdata_getUUID(tsp); - endpoint = clientEndpoint(uuid); - cci_debug_printf("%s Registering endpoint %s", __FUNCTION__, endpoint); opts.cMinCalls = 1; opts.cMaxCalls = 20; opts.fDontWait = TRUE; - if (!status) { - status = RpcServerUseProtseqEp((RPC_CSTR)"ncalrpc", - opts.cMaxCalls, - (RPC_CSTR)endpoint, - sa.lpSecurityDescriptor); // SD - cci_check_error(status); - } - - if (!status) { - status = RpcServerRegisterAuthInfo(0, // server principal - RPC_C_AUTHN_WINNT, - 0, - 0 ); - cci_check_error(status); - } - cci_debug_printf("%s is listening ...", __FUNCTION__); - if (!status) { - if (!isNT()) { - status = RpcServerRegisterIf(ccs_reply_ServerIfHandle, // interface - NULL, // MgrTypeUuid - NULL); // MgrEpv; null means use default - } - else { - status = RpcServerRegisterIfEx(ccs_reply_ServerIfHandle,// interface - NULL, // MgrTypeUuid - NULL, // MgrEpv; 0 means default - RPC_IF_ALLOW_SECURE_ONLY, - opts.cMaxCalls, - NULL); // No security callback. - } - - cci_check_error(status); - - if (!status) { - status = RpcServerListen(opts.cMinCalls, - opts.cMaxCalls, - TRUE); - cci_check_error(status); - } - } - // Clear replyEvent so we can detect when a reply to our connect request has been received: ResetEvent(replyEvent); diff --git a/src/ccapi/lib/win/debug.exports b/src/ccapi/lib/win/debug.exports index 583e9ca1ee..6dc1fc083a 100644 --- a/src/ccapi/lib/win/debug.exports +++ b/src/ccapi/lib/win/debug.exports @@ -8,3 +8,4 @@ krb5int_ipc_stream_new ccs_authenticate + cci_os_ipc_process_init diff --git a/src/ccapi/lib/win/dllmain.cxx b/src/ccapi/lib/win/dllmain.cxx index e37a9ad6bf..3141e190e7 100644 --- a/src/ccapi/lib/win/dllmain.cxx +++ b/src/ccapi/lib/win/dllmain.cxx @@ -32,9 +32,10 @@ extern "C" { #include "tls.h" #include "cci_debugging.h" #include "ccapi_context.h" +#include "ccapi_ipc.h" #include "client.h" -void cci_thread_init__auxinit(); +void cci_process_init__auxinit(); } @@ -91,10 +92,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle // Allocate a TLS index: if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE; - - // Initialize CCAPI once per DLL load: - firstThreadID = GetCurrentThreadId(); + cci_process_init__auxinit(); // Don't break; fallthrough: Initialize the TLS index for first thread. // The attached process creates a new thread: @@ -107,8 +106,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle memset(ptspdata, 0, sizeof(struct tspdata)); - // Initialize CCAPI once per DLL load: - if (GetCurrentThreadId() == firstThreadID) cci_thread_init__auxinit(); + // Initialize CCAPI thread data: + cci_ipc_thread_init(); break; -- cgit