Replace the use of Critical Sections for locking with Mutex's (thread.c). This appears to resolve a deadlock issue with OpenSSL on some Windows systems. This commit resolves a bug in interactive processes where an interactive waiter thread will chew cpu due to a tight loop introduced by anonymous pipes not blocking (process.c). Dynamic lock creation for OpenSSL has been re-enabled should a future version of OpenSSL require it, AFAIK the current version used, v0.8.9, does not use dynamic lock creation (server_setup.c). Channels have been given locks to help synchronize concurrent access to a single channel.

git-svn-id: file:///home/svn/framework3/trunk@7732 4d416f70-5f16-0410-b530-b9f4589650da
unstable
Stephen Fewer 2009-12-07 13:04:41 +00:00
parent 0b8917a39e
commit 4f8cfc27d4
10 changed files with 228 additions and 199 deletions

View File

@ -109,7 +109,7 @@ DWORD remote_request_core_channel_write(Remote *remote, Packet *packet)
Packet *response = packet_create_response(packet);
DWORD res = ERROR_SUCCESS, channelId, written = 0;
Tlv channelData;
Channel *channel;
Channel * channel = NULL;
do
{
@ -122,6 +122,8 @@ DWORD remote_request_core_channel_write(Remote *remote, Packet *packet)
break;
}
lock_acquire( channel->lock );
// Get the channel data buffer
if ((res = packet_get_tlv(packet, TLV_TYPE_CHANNEL_DATA, &channelData))
!= ERROR_SUCCESS)
@ -151,6 +153,9 @@ DWORD remote_request_core_channel_write(Remote *remote, Packet *packet)
} while (0);
if( channel )
lock_release( channel->lock );
// Transmit the acknowledgement
if (response)
{
@ -201,6 +206,8 @@ DWORD remote_request_core_channel_read(Remote *remote, Packet *packet)
break;
}
lock_acquire( channel->lock );
// Allocate temporary storage
if (!(temporaryBuffer = (PUCHAR)malloc(bytesToRead)))
{
@ -256,6 +263,9 @@ DWORD remote_request_core_channel_read(Remote *remote, Packet *packet)
}
} while (0);
if( channel )
lock_release( channel->lock );
if (temporaryBuffer)
free(temporaryBuffer);
@ -378,6 +388,8 @@ DWORD remote_request_core_channel_seek(Remote *remote, Packet *packet)
break;
}
lock_acquire( channel->lock );
// Make sure this class is compatible
if (channel_get_class(channel) != CHANNEL_CLASS_POOL)
{
@ -395,6 +407,9 @@ DWORD remote_request_core_channel_seek(Remote *remote, Packet *packet)
result = ERROR_NOT_SUPPORTED;
} while (0);
if( channel )
lock_release( channel->lock );
// Transmit the result
packet_transmit_response(result, remote, response);
@ -425,6 +440,8 @@ DWORD remote_request_core_channel_eof(Remote *remote, Packet *packet)
break;
}
lock_acquire( channel->lock );
// Make sure this class is compatible
if (channel_get_class(channel) != CHANNEL_CLASS_POOL)
{
@ -441,6 +458,9 @@ DWORD remote_request_core_channel_eof(Remote *remote, Packet *packet)
result = ERROR_NOT_SUPPORTED;
} while (0);
if( channel )
lock_release( channel->lock );
// Add the EOF flag
packet_add_tlv_bool(response, TLV_TYPE_BOOL, isEof);
@ -474,6 +494,8 @@ DWORD remote_request_core_channel_tell(Remote *remote, Packet *packet)
break;
}
lock_acquire( channel->lock );
// Make sure this class is compatible
if (channel_get_class(channel) != CHANNEL_CLASS_POOL)
{
@ -491,6 +513,9 @@ DWORD remote_request_core_channel_tell(Remote *remote, Packet *packet)
} while (0);
if( channel )
lock_release( channel->lock );
// Add the offset
packet_add_tlv_uint(response, TLV_TYPE_SEEK_POS, offset);
@ -511,7 +536,7 @@ DWORD remote_request_core_channel_tell(Remote *remote, Packet *packet)
DWORD remote_request_core_channel_interact(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
Channel *channel;
Channel *channel = NULL;
DWORD channelId;
DWORD result = ERROR_SUCCESS;
BOOLEAN interact;
@ -523,6 +548,8 @@ DWORD remote_request_core_channel_interact(Remote *remote, Packet *packet)
// If the channel is found, set the interactive flag accordingly
if ((channel = channel_find_by_id(channelId)))
{
lock_acquire( channel->lock );
// If the response packet is valid
if ((response) &&
(channel_get_class(channel) != CHANNEL_CLASS_BUFFERED))
@ -537,6 +564,8 @@ DWORD remote_request_core_channel_interact(Remote *remote, Packet *packet)
// Set the channel's interactive state
channel_set_interactive(channel, interact);
lock_release( channel->lock );
}
// Send the response to the requestor so that the interaction can be

View File

@ -45,6 +45,7 @@ Channel *channel_create(DWORD identifier, DWORD flags)
channel->interactive = FALSE;
channel->flags = flags;
channel->cls = CHANNEL_CLASS_BUFFERED;
channel->lock = lock_create();
memset(&channel->ops, 0, sizeof(channel->ops));
@ -155,6 +156,8 @@ VOID channel_destroy(Channel *channel, Packet *request)
// Remove the channel from the list of channels
channel_remove_list_entry(channel);
lock_destroy( channel->lock );
// Destroy the channel context
free(channel);
}

View File

@ -126,7 +126,8 @@ typedef struct _Channel
BOOL interactive;
// Operational flags
ULONG flags;
// Lock for synchronizing communication to a channel
LOCK * lock;
// The buffered output buffer (as in being outputted bufferedly)
union
{

View File

@ -6,7 +6,9 @@
/*****************************************************************************************/
/*
* Create a new lock.
* Create a new lock. We choose Mutex's over CriticalSections as their appears to be an issue
* when using CriticalSections with OpenSSL on some Windows systems. Mutex's are not as optimal
* as CriticalSections but they appear to resolve the OpenSSL deadlock issue.
*/
LOCK * lock_create( VOID )
{
@ -15,7 +17,7 @@ LOCK * lock_create( VOID )
{
memset( lock, 0, sizeof( LOCK ) );
InitializeCriticalSection( &lock->cs );
lock->handle = CreateMutex( NULL, FALSE, NULL );
}
return lock;
}
@ -29,7 +31,7 @@ VOID lock_destroy( LOCK * lock )
{
lock_release( lock );
DeleteCriticalSection( &lock->cs );
CloseHandle( lock->handle );
free( lock );
}
@ -41,19 +43,7 @@ VOID lock_destroy( LOCK * lock )
VOID lock_acquire( LOCK * lock )
{
if( lock != NULL )
EnterCriticalSection( &lock->cs );
}
/*
* Atempt to acquire a lock, returning true if lock is acquired or allready owned.
* Returns false if another thread has acquired the lock. This function does not block.
*/
BOOL lock_poll( LOCK * lock )
{
if( lock != NULL )
return TryEnterCriticalSection( &lock->cs );
return FALSE;
WaitForSingleObject( lock->handle, INFINITE );
}
/*
@ -62,7 +52,7 @@ BOOL lock_poll( LOCK * lock )
VOID lock_release( LOCK * lock )
{
if( lock != NULL )
LeaveCriticalSection( &lock->cs );
ReleaseMutex( lock->handle );
}
/*****************************************************************************************/

View File

@ -5,7 +5,7 @@
typedef struct _LOCK
{
CRITICAL_SECTION cs;
HANDLE handle;
} LOCK, * LPLOCK;
typedef struct _EVENT
@ -34,8 +34,6 @@ VOID lock_destroy( LOCK * lock );
VOID lock_acquire( LOCK * lock );
BOOL lock_poll( LOCK * lock );
VOID lock_release( LOCK * lock );
/*****************************************************************************************/

View File

@ -653,16 +653,24 @@ DWORD process_channel_interact_notify(Remote *remote, Channel *channel)
DWORD bytesRead, bytesAvail = 0;
CHAR buffer[16384];
// If data is read successfully from the handler, write it
// to the remote channel.
if ((PeekNamedPipe(ctx->pStdout, NULL, 0, NULL, &bytesAvail, NULL)) &&
(bytesAvail) &&
(ReadFile(ctx->pStdout, buffer, sizeof(buffer) - 1,
&bytesRead, NULL)))
channel_write(channel, remote, NULL, 0, buffer,
bytesRead, NULL);
// Otherwise, if things fail, close the channel
else if (GetLastError() != ERROR_SUCCESS)
if( PeekNamedPipe( ctx->pStdout, NULL, 0, NULL, &bytesAvail, NULL ) )
{
if( bytesAvail )
{
if( ReadFile( ctx->pStdout, buffer, sizeof(buffer) - 1, &bytesRead, NULL ) )
{
return channel_write( channel, remote, NULL, 0, buffer, bytesRead, NULL );
}
}
else
{
// sf: if no data is available on the pipe we sleep to avoid running a tight loop
// in this thread, as anonymous pipes won't block for data to arrive.
Sleep( 100 );
}
}
if( GetLastError() != ERROR_SUCCESS )
{
process_channel_close( channel, NULL, ctx );
channel_close( channel, remote, NULL, 0, NULL );

View File

@ -170,7 +170,7 @@ static BOOL server_initialize_ssl( Remote * remote )
SSL_library_init();
// Setup the required OpenSSL multi-threaded enviroment...
ssl_locks = (LOCK**)malloc( CRYPTO_num_locks() * sizeof(LOCK) );
ssl_locks = (LOCK**)malloc( CRYPTO_num_locks() * sizeof(LOCK *) );
if( ssl_locks == NULL )
{
lock_release( remote->lock );
@ -182,10 +182,9 @@ static BOOL server_initialize_ssl( Remote * remote )
CRYPTO_set_id_callback( server_threadid_callback );
CRYPTO_set_locking_callback( server_locking_callback );
// sf: unsure if these are required or giving optimal performance, commenting out for now.
//CRYPTO_set_dynlock_create_callback( server_dynamiclock_create );
//CRYPTO_set_dynlock_lock_callback( server_dynamiclock_lock );
//CRYPTO_set_dynlock_destroy_callback( server_dynamiclock_destroy );
CRYPTO_set_dynlock_create_callback( server_dynamiclock_create );
CRYPTO_set_dynlock_lock_callback( server_dynamiclock_lock );
CRYPTO_set_dynlock_destroy_callback( server_dynamiclock_destroy );
lock_release( remote->lock );
@ -210,9 +209,9 @@ static BOOL server_destroy_ssl( Remote * remote )
CRYPTO_set_locking_callback( NULL );
CRYPTO_set_id_callback( NULL );
//CRYPTO_set_dynlock_create_callback( NULL );
//CRYPTO_set_dynlock_lock_callback( NULL );
//CRYPTO_set_dynlock_destroy_callback( NULL );
CRYPTO_set_dynlock_create_callback( NULL );
CRYPTO_set_dynlock_lock_callback( NULL );
CRYPTO_set_dynlock_destroy_callback( NULL );
for( i=0 ; i<CRYPTO_num_locks() ; i++ )
lock_destroy( ssl_locks[i] );

View File

@ -81,6 +81,69 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN64;_DEBUG;_LIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
IgnoreDefaultLibraryNames="libcmtd"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
@ -147,69 +210,6 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN64;_DEBUG;_LIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
IgnoreDefaultLibraryNames="libcmtd"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"

View File

@ -91,98 +91,6 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
EnableIntrinsicFunctions="false"
AdditionalIncludeDirectories="..\..\source\extensions\espia;..\..\source\openssl\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_ESPIA_EXPORTS"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="Netapi32.lib Mpr.lib metsrv.lib"
OutputFile=".\Release/ext_server_espia.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\metsrv\Release;;..\..\source\openssl\lib\win"
GenerateManifest="false"
DelayLoadDLLs="metsrv.dll"
GenerateDebugInformation="false"
GenerateMapFile="true"
MapFileName=".\Release/ext_server_espia.map"
SubSystem="0"
OptimizeReferences="0"
EnableCOMDATFolding="0"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Release/ext_server_espia.lib"
TargetMachine="1"
Profile="false"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="copy /y &quot;$(ProjectDir)\release\*.dll&quot; &quot;$(ProjectDir)..\..\output\&quot;"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
@ -256,6 +164,98 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
EnableIntrinsicFunctions="false"
AdditionalIncludeDirectories="..\..\source\extensions\espia;..\..\source\openssl\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_ESPIA_EXPORTS"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="Netapi32.lib Mpr.lib metsrv.lib"
OutputFile=".\Release/ext_server_espia.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\metsrv\Release;..\..\source\openssl\lib\win"
GenerateManifest="false"
DelayLoadDLLs="metsrv.dll"
GenerateDebugInformation="false"
GenerateMapFile="true"
MapFileName=".\Release/ext_server_espia.map"
SubSystem="0"
OptimizeReferences="0"
EnableCOMDATFolding="0"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Release/ext_server_espia.lib"
TargetMachine="1"
Profile="false"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="copy /y &quot;$(ProjectDir)\release\*.dll&quot; &quot;$(ProjectDir)..\..\output\&quot;"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
@ -309,7 +309,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="Netapi32.lib Mpr.lib metsrv.lib"
OutputFile=".\Release/ext_server_espia.dll"
OutputFile=".\Release\ext_server_espia.x64.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\metsrv\Release;;..\..\source\openssl\lib\win"
GenerateManifest="false"
@ -346,7 +346,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="copy /y &quot;$(ProjectDir)\release\*.dll&quot; &quot;$(ProjectDir)..\..\output\&quot;"
CommandLine="copy /y &quot;$(ProjectDir)\release\ext_server_espia.x64.dll&quot; &quot;$(ProjectDir)..\..\output\&quot;"
/>
</Configuration>
</Configurations>

View File

@ -133,7 +133,8 @@ Global
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Debug|x64.ActiveCfg = Debug|Win32
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Release|Win32.ActiveCfg = Release|Win32
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Release|Win32.Build.0 = Release|Win32
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Release|x64.ActiveCfg = Release|Win32
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Release|x64.ActiveCfg = Release|x64
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Release|x64.Build.0 = Release|x64
{BF0C0D6E-9119-4518-A3BC-2CF99C0E27D9}.Debug|Win32.ActiveCfg = Debug|Win32
{BF0C0D6E-9119-4518-A3BC-2CF99C0E27D9}.Debug|Win32.Build.0 = Debug|Win32
{BF0C0D6E-9119-4518-A3BC-2CF99C0E27D9}.Debug|x64.ActiveCfg = Debug|x64