зеркало из https://github.com/mozilla/pjs.git
Fix for 102251 . Implement 2-level locking for the SSL session cache to properly support SSL server applications using Windows NT fibers . Also optimize and enhance portability of locking primitives for single-process servers on all platforms by using a PRLock instead of cross-process locks . Reviewed by wtc
This commit is contained in:
Родитель
644c4d90a3
Коммит
d846685687
|
@ -30,12 +30,59 @@
|
|||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: sslmutex.c,v 1.3 2001-06-12 22:53:00 nelsonb%netscape.com Exp $
|
||||
* $Id: sslmutex.c,v 1.4 2001-10-06 00:14:33 jpierre%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "sslmutex.h"
|
||||
#include "prerr.h"
|
||||
|
||||
static SECStatus single_process_sslMutex_Init(sslMutex* pMutex)
|
||||
{
|
||||
PR_ASSERT(pMutex != 0 && pMutex->u.sslLock == 0 );
|
||||
|
||||
pMutex->u.sslLock = PR_NewLock();
|
||||
if (!pMutex->u.sslLock) {
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus single_process_sslMutex_Destroy(sslMutex* pMutex)
|
||||
{
|
||||
PR_ASSERT(pMutex != 0);
|
||||
PR_ASSERT(pMutex->u.sslLock!= 0);
|
||||
if (!pMutex->u.sslLock) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
PR_DestroyLock(pMutex->u.sslLock);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus single_process_sslMutex_Unlock(sslMutex* pMutex)
|
||||
{
|
||||
PR_ASSERT(pMutex != 0 );
|
||||
PR_ASSERT(pMutex->u.sslLock !=0);
|
||||
if (!pMutex->u.sslLock) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
PR_Unlock(pMutex->u.sslLock);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus single_process_sslMutex_Lock(sslMutex* pMutex)
|
||||
{
|
||||
PR_ASSERT(pMutex != 0);
|
||||
PR_ASSERT(pMutex->u.sslLock != 0 );
|
||||
if (!pMutex->u.sslLock) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
PR_Lock(pMutex->u.sslLock);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
#if defined(LINUX) || defined(AIX)
|
||||
|
||||
#include <unistd.h>
|
||||
|
@ -76,34 +123,38 @@ SECStatus
|
|||
sslMutex_Init(sslMutex *pMutex, int shared)
|
||||
{
|
||||
int err;
|
||||
PR_ASSERT(pMutex);
|
||||
pMutex->isMultiProcess = (PRBool)(shared != 0);
|
||||
if (!shared) {
|
||||
return single_process_sslMutex_Init(pMutex);
|
||||
}
|
||||
pMutex->u.pipeStr.mPipes[0] = -1;
|
||||
pMutex->u.pipeStr.mPipes[1] = -1;
|
||||
pMutex->u.pipeStr.mPipes[2] = -1;
|
||||
pMutex->u.pipeStr.nWaiters = 0;
|
||||
|
||||
pMutex->mPipes[0] = -1;
|
||||
pMutex->mPipes[1] = -1;
|
||||
pMutex->mPipes[2] = -1;
|
||||
pMutex->nWaiters = 0;
|
||||
|
||||
err = pipe(pMutex->mPipes);
|
||||
err = pipe(pMutex->u.pipeStr.mPipes);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
/* close-on-exec is false by default */
|
||||
if (!shared) {
|
||||
err = fcntl(pMutex->mPipes[0], F_SETFD, FD_CLOEXEC);
|
||||
err = fcntl(pMutex->u.pipeStr.mPipes[0], F_SETFD, FD_CLOEXEC);
|
||||
if (err)
|
||||
goto loser;
|
||||
|
||||
err = fcntl(pMutex->mPipes[1], F_SETFD, FD_CLOEXEC);
|
||||
err = fcntl(pMutex->u.pipeStr.mPipes[1], F_SETFD, FD_CLOEXEC);
|
||||
if (err)
|
||||
goto loser;
|
||||
}
|
||||
|
||||
#if NONBLOCKING_POSTS
|
||||
err = setNonBlocking(pMutex->mPipes[1], 1);
|
||||
err = setNonBlocking(pMutex->u.pipeStr.mPipes[1], 1);
|
||||
if (err)
|
||||
goto loser;
|
||||
#endif
|
||||
|
||||
pMutex->mPipes[2] = SSL_MUTEX_MAGIC;
|
||||
pMutex->u.pipeStr.mPipes[2] = SSL_MUTEX_MAGIC;
|
||||
|
||||
#if defined(LINUX) && defined(i386)
|
||||
/* Pipe starts out empty */
|
||||
|
@ -115,25 +166,28 @@ sslMutex_Init(sslMutex *pMutex, int shared)
|
|||
|
||||
loser:
|
||||
nss_MD_unix_map_default_error(errno);
|
||||
close(pMutex->mPipes[0]);
|
||||
close(pMutex->mPipes[1]);
|
||||
close(pMutex->u.pipeStr.mPipes[0]);
|
||||
close(pMutex->u.pipeStr.mPipes[1]);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
sslMutex_Destroy(sslMutex *pMutex)
|
||||
{
|
||||
if (pMutex->mPipes[2] != SSL_MUTEX_MAGIC) {
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Destroy(pMutex);
|
||||
}
|
||||
if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
close(pMutex->mPipes[0]);
|
||||
close(pMutex->mPipes[1]);
|
||||
close(pMutex->u.pipeStr.mPipes[0]);
|
||||
close(pMutex->u.pipeStr.mPipes[1]);
|
||||
|
||||
pMutex->mPipes[0] = -1;
|
||||
pMutex->mPipes[1] = -1;
|
||||
pMutex->mPipes[2] = -1;
|
||||
pMutex->nWaiters = 0;
|
||||
pMutex->u.pipeStr.mPipes[0] = -1;
|
||||
pMutex->u.pipeStr.mPipes[1] = -1;
|
||||
pMutex->u.pipeStr.mPipes[2] = -1;
|
||||
pMutex->u.pipeStr.nWaiters = 0;
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
@ -145,6 +199,9 @@ SECStatus
|
|||
sslMutex_Unlock(sslMutex *pMutex)
|
||||
{
|
||||
PRInt32 oldValue;
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Unlock(pMutex);
|
||||
}
|
||||
|
||||
if (pMutex->mPipes[2] != SSL_MUTEX_MAGIC) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
|
@ -173,6 +230,9 @@ SECStatus
|
|||
sslMutex_Lock(sslMutex *pMutex)
|
||||
{
|
||||
PRInt32 oldValue;
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Lock(pMutex);
|
||||
}
|
||||
|
||||
if (pMutex->mPipes[2] != SSL_MUTEX_MAGIC) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
|
@ -211,12 +271,16 @@ sslMutex_Unlock(sslMutex *pMutex)
|
|||
int cc;
|
||||
char c = 1;
|
||||
|
||||
if (pMutex->mPipes[2] != SSL_MUTEX_MAGIC) {
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Unlock(pMutex);
|
||||
}
|
||||
|
||||
if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
do {
|
||||
cc = write(pMutex->mPipes[1], &c, 1);
|
||||
cc = write(pMutex->u.pipeStr.mPipes[1], &c, 1);
|
||||
} while (cc < 0 && (errno == EINTR || errno == EAGAIN));
|
||||
if (cc != 1) {
|
||||
if (cc < 0)
|
||||
|
@ -235,13 +299,17 @@ sslMutex_Lock(sslMutex *pMutex)
|
|||
int cc;
|
||||
char c;
|
||||
|
||||
if (pMutex->mPipes[2] != SSL_MUTEX_MAGIC) {
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Lock(pMutex);
|
||||
}
|
||||
|
||||
if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
do {
|
||||
cc = read(pMutex->mPipes[0], &c, 1);
|
||||
cc = read(pMutex->u.pipeStr.mPipes[0], &c, 1);
|
||||
} while (cc < 0 && errno == EINTR);
|
||||
if (cc != 1) {
|
||||
if (cc < 0)
|
||||
|
@ -260,22 +328,69 @@ sslMutex_Lock(sslMutex *pMutex)
|
|||
|
||||
#include "win32err.h"
|
||||
|
||||
/* The presence of the TRUE element in this struct makes the semaphore
|
||||
* inheritable. The NULL means use process's default security descriptor.
|
||||
*/
|
||||
/* on Windows, we need to find the optimal type of locking mechanism to use
|
||||
for the sslMutex.
|
||||
|
||||
There are 3 cases :
|
||||
1) single-process, use a PRLock, as for all other platforms
|
||||
2) Win95 multi-process, use a Win32 mutex
|
||||
3) on WINNT multi-process, use a PRLock + a Win32 mutex
|
||||
|
||||
*/
|
||||
|
||||
#ifdef WINNT
|
||||
|
||||
SECStatus sslMutex_2LevelInit(sslMutex *sem)
|
||||
{
|
||||
/* the following adds a PRLock to sslMutex . This is done in each
|
||||
process of a multi-process server and is only needed on WINNT, if
|
||||
using fibers. We can't tell if native threads or fibers are used, so
|
||||
we always do it on WINNT
|
||||
*/
|
||||
PR_ASSERT(sem);
|
||||
if (sem) {
|
||||
/* we need to reset the sslLock in the children or the 2Level init
|
||||
function below will assert */
|
||||
sem->u.sslLock = NULL;
|
||||
}
|
||||
return single_process_sslMutex_Init(sem);
|
||||
}
|
||||
|
||||
static SECStatus sslMutex_2LevelDestroy(sslMutex *sem)
|
||||
{
|
||||
return single_process_sslMutex_Destroy(sem);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
SECStatus
|
||||
sslMutex_Init(sslMutex *pMutex, int shared)
|
||||
{
|
||||
|
||||
SECStatus retvalue;
|
||||
HANDLE hMutex;
|
||||
SECURITY_ATTRIBUTES attributes =
|
||||
{ sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
|
||||
|
||||
PR_ASSERT(pMutex != 0 && (*pMutex == 0 || *pMutex == INVALID_HANDLE_VALUE));
|
||||
if (!pMutex || ((hMutex = *pMutex) != 0 && hMutex != INVALID_HANDLE_VALUE)) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
return SECFailure;
|
||||
PR_ASSERT(pMutex != 0 && (pMutex->u.sslMutx == 0 ||
|
||||
pMutex->u.sslMutx == INVALID_HANDLE_VALUE) );
|
||||
|
||||
pMutex->isMultiProcess = (PRBool)(shared != 0);
|
||||
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Init(pMutex);
|
||||
}
|
||||
|
||||
#ifdef WINNT
|
||||
/* we need a lock on WINNT for fibers in the parent process */
|
||||
retvalue = sslMutex_2LevelInit(pMutex);
|
||||
if (SECSuccess != retvalue)
|
||||
return SECFailure;
|
||||
#endif
|
||||
|
||||
if (!pMutex || ((hMutex = pMutex->u.sslMutx) != 0 &&
|
||||
hMutex != INVALID_HANDLE_VALUE)) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
attributes.bInheritHandle = (shared ? TRUE : FALSE);
|
||||
hMutex = CreateMutex(&attributes, FALSE, NULL);
|
||||
|
@ -284,28 +399,44 @@ sslMutex_Init(sslMutex *pMutex, int shared)
|
|||
nss_MD_win32_map_default_error(GetLastError());
|
||||
return SECFailure;
|
||||
}
|
||||
*pMutex = hMutex;
|
||||
pMutex->u.sslMutx = hMutex;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
int
|
||||
SECStatus
|
||||
sslMutex_Destroy(sslMutex *pMutex)
|
||||
{
|
||||
HANDLE hMutex;
|
||||
int rv;
|
||||
int retvalue = SECSuccess;
|
||||
|
||||
PR_ASSERT(pMutex != 0 && *pMutex != 0 && *pMutex != INVALID_HANDLE_VALUE);
|
||||
if (!pMutex || (hMutex = *pMutex) == 0 || hMutex == INVALID_HANDLE_VALUE) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
return SECFailure;
|
||||
PR_ASSERT(pMutex != 0);
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Destroy(pMutex);
|
||||
}
|
||||
|
||||
/* multi-process mode */
|
||||
#ifdef WINNT
|
||||
/* on NT, get rid of the PRLock used for fibers within a process */
|
||||
retvalue = sslMutex_2LevelDestroy(pMutex);
|
||||
#endif
|
||||
|
||||
PR_ASSERT( pMutex->u.sslMutx != 0 &&
|
||||
pMutex->u.sslMutx != INVALID_HANDLE_VALUE);
|
||||
if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0
|
||||
|| hMutex == INVALID_HANDLE_VALUE) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = CloseHandle(hMutex); /* ignore error */
|
||||
if (rv) {
|
||||
*pMutex = hMutex = INVALID_HANDLE_VALUE;
|
||||
return SECSuccess;
|
||||
pMutex->u.sslMutx = hMutex = INVALID_HANDLE_VALUE;
|
||||
} else {
|
||||
nss_MD_win32_map_default_error(GetLastError());
|
||||
retvalue = SECFailure;
|
||||
}
|
||||
nss_MD_win32_map_default_error(GetLastError());
|
||||
return SECFailure;
|
||||
return retvalue;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -314,17 +445,29 @@ sslMutex_Unlock(sslMutex *pMutex)
|
|||
BOOL success = FALSE;
|
||||
HANDLE hMutex;
|
||||
|
||||
PR_ASSERT(pMutex != 0 && *pMutex != 0 && *pMutex != INVALID_HANDLE_VALUE);
|
||||
if (!pMutex || (hMutex = *pMutex) == 0 || hMutex == INVALID_HANDLE_VALUE) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
return SECFailure;
|
||||
PR_ASSERT(pMutex != 0 );
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Unlock(pMutex);
|
||||
}
|
||||
|
||||
PR_ASSERT(pMutex->u.sslMutx != 0 &&
|
||||
pMutex->u.sslMutx != INVALID_HANDLE_VALUE);
|
||||
if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 ||
|
||||
hMutex == INVALID_HANDLE_VALUE) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
success = ReleaseMutex(hMutex);
|
||||
if (!success) {
|
||||
nss_MD_win32_map_default_error(GetLastError());
|
||||
return SECFailure;
|
||||
}
|
||||
#ifdef WINNT
|
||||
return single_process_sslMutex_Unlock(pMutex);
|
||||
/* release PRLock for other fibers in the process */
|
||||
#else
|
||||
return SECSuccess;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -334,12 +477,25 @@ sslMutex_Lock(sslMutex *pMutex)
|
|||
DWORD event;
|
||||
DWORD lastError;
|
||||
SECStatus rv;
|
||||
SECStatus retvalue = SECSuccess;
|
||||
PR_ASSERT(pMutex != 0);
|
||||
|
||||
PR_ASSERT(pMutex != 0 && *pMutex != 0 && *pMutex != INVALID_HANDLE_VALUE);
|
||||
if (!pMutex || (hMutex = *pMutex) == 0 || hMutex == INVALID_HANDLE_VALUE) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Lock(pMutex);
|
||||
}
|
||||
#ifdef WINNT
|
||||
/* lock first to preserve from other threads/fibers
|
||||
in the same process */
|
||||
retvalue = single_process_sslMutex_Lock(pMutex);
|
||||
#endif
|
||||
PR_ASSERT(pMutex->u.sslMutx != 0 &&
|
||||
pMutex->u.sslMutx != INVALID_HANDLE_VALUE);
|
||||
if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 ||
|
||||
hMutex == INVALID_HANDLE_VALUE) {
|
||||
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
|
||||
return SECFailure; /* what else ? */
|
||||
}
|
||||
/* acquire the mutex to be the only owner accross all other processes */
|
||||
event = WaitForSingleObject(hMutex, INFINITE);
|
||||
switch (event) {
|
||||
case WAIT_OBJECT_0:
|
||||
|
@ -361,7 +517,12 @@ sslMutex_Lock(sslMutex *pMutex)
|
|||
nss_MD_win32_map_default_error(lastError);
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
|
||||
if (! (SECSuccess == retvalue && SECSuccess == rv)) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
#elif defined(XP_UNIX)
|
||||
|
@ -373,12 +534,17 @@ SECStatus
|
|||
sslMutex_Init(sslMutex *pMutex, int shared)
|
||||
{
|
||||
int rv;
|
||||
PR_ASSERT(pMutex);
|
||||
pMutex->isMultiProcess = (PRBool)(shared != 0);
|
||||
if (!shared) {
|
||||
return single_process_sslMutex_Init(pMutex);
|
||||
}
|
||||
do {
|
||||
rv = sem_init(pMutex, shared, 1);
|
||||
rv = sem_init(&pMutex->u.sem, shared, 1);
|
||||
} while (rv < 0 && errno == EINTR);
|
||||
if (rv < 0) {
|
||||
nss_MD_unix_map_default_error(errno);
|
||||
return SECFailure;
|
||||
nss_MD_unix_map_default_error(errno);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
@ -387,8 +553,11 @@ SECStatus
|
|||
sslMutex_Destroy(sslMutex *pMutex)
|
||||
{
|
||||
int rv;
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Destroy(pMutex);
|
||||
}
|
||||
do {
|
||||
rv = sem_destroy(pMutex);
|
||||
rv = sem_destroy(&pMutex->u.sem);
|
||||
} while (rv < 0 && errno == EINTR);
|
||||
if (rv < 0) {
|
||||
nss_MD_unix_map_default_error(errno);
|
||||
|
@ -401,8 +570,11 @@ SECStatus
|
|||
sslMutex_Unlock(sslMutex *pMutex)
|
||||
{
|
||||
int rv;
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Unlock(pMutex);
|
||||
}
|
||||
do {
|
||||
rv = sem_post(pMutex);
|
||||
rv = sem_post(&pMutex->u.sem);
|
||||
} while (rv < 0 && errno == EINTR);
|
||||
if (rv < 0) {
|
||||
nss_MD_unix_map_default_error(errno);
|
||||
|
@ -415,8 +587,11 @@ SECStatus
|
|||
sslMutex_Lock(sslMutex *pMutex)
|
||||
{
|
||||
int rv;
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Lock(pMutex);
|
||||
}
|
||||
do {
|
||||
rv = sem_wait(pMutex);
|
||||
rv = sem_wait(&pMutex->u.sem);
|
||||
} while (rv < 0 && errno == EINTR);
|
||||
if (rv < 0) {
|
||||
nss_MD_unix_map_default_error(errno);
|
||||
|
@ -430,7 +605,12 @@ sslMutex_Lock(sslMutex *pMutex)
|
|||
SECStatus
|
||||
sslMutex_Init(sslMutex *pMutex, int shared)
|
||||
{
|
||||
PORT_Assert(!("sslMutex_Init not implemented!"));
|
||||
PR_ASSERT(pMutex);
|
||||
pMutex->isMultiProcess = (PRBool)(shared != 0);
|
||||
if (!shared) {
|
||||
return single_process_sslMutex_Init(pMutex);
|
||||
}
|
||||
PORT_Assert(!("sslMutex_Init not implemented for multi-process applications !"));
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
@ -438,7 +618,11 @@ sslMutex_Init(sslMutex *pMutex, int shared)
|
|||
SECStatus
|
||||
sslMutex_Destroy(sslMutex *pMutex)
|
||||
{
|
||||
PORT_Assert(!("sslMutex_Destroy not implemented!"));
|
||||
PR_ASSERT(pMutex);
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Destroy(pMutex);
|
||||
}
|
||||
PORT_Assert(!("sslMutex_Destroy not implemented for multi-process applications !"));
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
@ -446,7 +630,11 @@ sslMutex_Destroy(sslMutex *pMutex)
|
|||
SECStatus
|
||||
sslMutex_Unlock(sslMutex *pMutex)
|
||||
{
|
||||
PORT_Assert(!("sslMutex_Unlock not implemented!"));
|
||||
PR_ASSERT(pMutex);
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Unlock(pMutex);
|
||||
}
|
||||
PORT_Assert(!("sslMutex_Unlock not implemented for multi-process applications !"));
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
@ -454,7 +642,11 @@ sslMutex_Unlock(sslMutex *pMutex)
|
|||
SECStatus
|
||||
sslMutex_Lock(sslMutex *pMutex)
|
||||
{
|
||||
PORT_Assert(!("sslMutex_Lock not implemented!"));
|
||||
PR_ASSERT(pMutex);
|
||||
if (PR_FALSE == pMutex->isMultiProcess) {
|
||||
return single_process_sslMutex_Lock(pMutex);
|
||||
}
|
||||
PORT_Assert(!("sslMutex_Lock not implemented for multi-process applications !"));
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: sslmutex.h,v 1.2 2001-06-12 01:10:01 nelsonb%netscape.com Exp $
|
||||
* $Id: sslmutex.h,v 1.3 2001-10-06 00:14:33 jpierre%netscape.com Exp $
|
||||
*/
|
||||
#ifndef __SSLMUTEX_H_
|
||||
#define __SSLMUTEX_H_ 1
|
||||
|
@ -54,10 +54,27 @@
|
|||
* So, this API looks a lot like POSIX pthread mutexes.
|
||||
*/
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "prlock.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
#include <wtypes.h>
|
||||
typedef HANDLE sslMutex;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PRBool isMultiProcess;
|
||||
#ifdef WINNT
|
||||
/* on WINNT we need both the PRLock and the Win32 mutex for fibers */
|
||||
struct {
|
||||
#else
|
||||
union {
|
||||
#endif
|
||||
PRLock* sslLock;
|
||||
HANDLE sslMutx;
|
||||
} u;
|
||||
} sslMutex;
|
||||
|
||||
typedef int sslPID;
|
||||
|
||||
#elif defined(LINUX) || defined(AIX)
|
||||
|
@ -66,8 +83,14 @@ typedef int sslPID;
|
|||
#include "prtypes.h"
|
||||
|
||||
typedef struct {
|
||||
int mPipes[3];
|
||||
PRInt32 nWaiters;
|
||||
PRBool isMultiProcess;
|
||||
union {
|
||||
PRLock* sslLock;
|
||||
struct {
|
||||
int mPipes[3];
|
||||
PRInt32 nWaiters;
|
||||
} pipeStr;
|
||||
} u;
|
||||
} sslMutex;
|
||||
typedef pid_t sslPID;
|
||||
|
||||
|
@ -76,14 +99,29 @@ typedef pid_t sslPID;
|
|||
#include <sys/types.h> /* for pid_t */
|
||||
#include <semaphore.h> /* for sem_t, and sem_* functions */
|
||||
|
||||
typedef sem_t sslMutex;
|
||||
typedef struct
|
||||
{
|
||||
PRBool isMultiProcess;
|
||||
union {
|
||||
PRLock* sslLock;
|
||||
sem_t sem;
|
||||
} u;
|
||||
} sslMutex;
|
||||
|
||||
typedef pid_t sslPID;
|
||||
|
||||
#else
|
||||
|
||||
/* what platform is this ?? */
|
||||
|
||||
typedef int sslMutex;
|
||||
typedef struct {
|
||||
PRBool isMultiProcess;
|
||||
union {
|
||||
PRLock* sslLock;
|
||||
/* include cross-process locking mechanism here */
|
||||
} u;
|
||||
} sslMutex;
|
||||
|
||||
typedef int sslPID;
|
||||
|
||||
#endif
|
||||
|
@ -100,6 +138,12 @@ extern SECStatus sslMutex_Unlock(sslMutex *sem);
|
|||
|
||||
extern SECStatus sslMutex_Lock(sslMutex *sem);
|
||||
|
||||
#ifdef WINNT
|
||||
|
||||
extern SECStatus sslMutex_2LevelInit(sslMutex *sem);
|
||||
|
||||
#endif
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: sslsnce.c,v 1.14 2001-09-18 01:59:20 nelsonb%netscape.com Exp $
|
||||
* $Id: sslsnce.c,v 1.15 2001-10-06 00:14:33 jpierre%netscape.com Exp $
|
||||
*/
|
||||
|
||||
/* Note: ssl_FreeSID() in sslnonce.c gets used for both client and server
|
||||
|
@ -1180,6 +1180,11 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
|
|||
ptrdiff_t ptr;
|
||||
inheritance inherit;
|
||||
cacheDesc my;
|
||||
#ifdef WINNT
|
||||
sidCacheLock* newLocks;
|
||||
int locks_initialized = 0;
|
||||
int locks_to_initialize = 0;
|
||||
#endif
|
||||
|
||||
myPid = SSL_GETPID();
|
||||
|
||||
|
@ -1261,6 +1266,40 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
|
|||
*(ptrdiff_t *)(&cache->certCacheData) += ptr;
|
||||
*(ptrdiff_t *)(&cache->keyCacheData ) += ptr;
|
||||
|
||||
#ifdef WINNT
|
||||
/* On Windows NT we need to "fix" the sidCacheLocks here to support fibers
|
||||
When NT fibers are used in a multi-process server, a second level of
|
||||
locking is needed to prevent a deadlock, in case a fiber acquires the
|
||||
cross-process mutex, yields, and another fiber is later scheduled on
|
||||
the same native thread and tries to acquire the cross-process mutex.
|
||||
We do this by using a PRLock in the sslMutex. However, it is stored in
|
||||
shared memory as part of sidCacheLocks, and we don't want to overwrite
|
||||
the PRLock of the parent process. So we need to make new, private
|
||||
copies of sidCacheLocks before modifying the sslMutex with our own
|
||||
PRLock
|
||||
*/
|
||||
|
||||
newLocks = (sidCacheLock*)PORT_Alloc(sizeof(sidCacheLock)*(cache->numSIDCacheLocks + 2));
|
||||
/* note from jpierre : this should be free'd in child processes when
|
||||
a function is added to delete the SSL session cache in the future */
|
||||
/* fix the locks */
|
||||
for (locks_to_initialize = cache->numSIDCacheLocks + 2;
|
||||
locks_initialized < locks_to_initialize;
|
||||
++locks_initialized) {
|
||||
/* copy the old lock */
|
||||
memcpy(&newLocks[locks_initialized], &cache->sidCacheLocks[locks_initialized], sizeof(sidCacheLock));
|
||||
/* now, make a local PRLock in this sslMutex for this child process */
|
||||
sslMutex_2LevelInit(&newLocks[locks_initialized].mutex);
|
||||
}
|
||||
|
||||
/* then, make our cache object point to our new private sidCacheLocks */
|
||||
/* first the session cache */
|
||||
cache->sidCacheLocks = newLocks;
|
||||
/* also fix the key and cert cache which use the last 2 lock entries */
|
||||
cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
|
||||
cache->certCacheLock = cache->keyCacheLock + 1;
|
||||
#endif
|
||||
|
||||
PORT_Free(decoString);
|
||||
isMultiProcess = PR_TRUE;
|
||||
return SECSuccess;
|
||||
|
|
Загрузка…
Ссылка в новой задаче