Latest release of The Server Framework: 6.6.5

Version 6.6.5 of The Server Framework was released today.

This release is mainly a feature release with a few bug fixes.

As always, see the release notes here, for full details of all changes.

Bug fixes:

  • Bug fix to JetByteTools::Socket::TAsyncSocket::ProcessAndGetNextOperation(). We now wrap the body of the function in an exception handler and abort the connection with JetByteTools::Socket::ConnectionClosureReason::FatalErrorAbort if an exception is thrown during processing. This fixes a bug whereby the connection would otherwise hang in these situations.
  • Bug fix to JetByteTools::Win32::TReentrantLockableObjectTracksLockingThread to add a cast which is needed for some compilers.
  • Bug fix to JetByteTools::WebSocket::HyBi::CProtocolHandler::HandleData() to remove an incorrect internal state validation exception which would generate spurious “No space left in read buffer.” exceptions.


  • Added JetByteTools::IO::IBuffer::OnBufferAddedToPool(), JetByteTools::IO::IBuffer::OnBufferRemovedFromPool(), JetByteTools::IO::IManageBufferLifeCycle::OnBufferAddedToPool() and JetByteTools::IO::IManageBufferLifeCycle::OnBufferRemovedFromPool(). These allow for correct management of dynamically allocated buffer data. Previously JetByteTools::IO::IMonitorBufferAllocation::OnBufferAllocated() was called whenever a buffer was allocated from the allocator OR a custom pool and JetByteTools::IO::IMonitorBufferAllocation::OnBufferReleased() was only called when the buffer was released to the allocator. This made it impossible to manage dynamically allocated buffer data that was created and destroyed by a derived allocator object using the monitoring interface to monitor the underlying allocator. Now JetByteTools::IO::IMonitorBufferAllocation::OnBufferReleased() is called when the buffer is added to a custom pool and this allows the monitor to match allocations and releases exactly.
  • Added JetByteTools::IO::IAllocateBuffers::AllocateCustomSizedBuffer() which allows you to allocate a custom buffer from any allocator. The buffer will have the same user data slots as any other buffer allocated from the allocator but if it is larger than the allocator’s buffer size the new buffer will NOT be pooled upon release.
  • Added JETBYTE_ILLEGAL_BUFFER_USER_DATA_EXCEPTIONS which defaults to 0 and when set turns on range checking for user data indices in JetByteTools::IO::CBuffer and an index out of range exception is thrown if necessary.
  • Added the ability to pass JUST a custom allocator into the constructor of JetByteTools::IO::CRotatingAsyncFileLog and allow the file log to manage the other resources that it needs directly. Previously you had to provide all of the resources or none.
  • Added an override for JetByteTools::Socket::ISocketCallback::OnError() which takes a DWORD error code so that client code can selectively ignore errors by error code. Previously the only way to ignore errors was by the error message itself which is localised and therefore impossible to match reliably.
  • Rationalised the status changes for JetByteTools::Socket::TStreamSocketServer<> and JetByteTools::Socket::TStreamSocketServerEx<> to remove some strangeness when shutdowns are initiated after the server has already shut down.
  • Added new value to JetByteTools::Socket::ConnectionClosureReason, FatalErrorAbort. This is used if the framework itself needs to abort a connection for any reason.
  • Added JetByteTools::Socket::CStreamSocketNamedConnectionCollection::GetConnectionName() which returns the name of a given connection.
  • Added JetByteTools::Socket::CStreamSocketBroadcastableConnectionCollection::BroadcastToAllExcept() which broadcasts a buffer to all connections except the supplied connection.
  • Added JetByteTools::Socket::StreamSocketBroadcastableNamedConnectionCollection.
  • Added JETBYTE_TRACK_ADDRESS_REFERENCES which defaults to 0 and when set enables reference tracking of JetByteTools::Socket::CAddressImpl objects in the same way that tracking can be enabled for sockets and buffers.
  • Added JETBYTE_STREAM_SOCKETS_DISPATCH_OTHER_SOCKETS_DURING_COMPLETION_HANDLING and JETBYTE_DATAGRAM_SOCKETS_DISPATCH_OTHER_SOCKETS_DURING_COMPLETION_HANDLING which both default to 0 and this changes the default behaviour from previous releases. These control how we deal with dispatching operations from other sockets whilst dispatching events from a socket… This only affects designs where one connection can write to another connection. In such a design, in earlier versions, we would allow processing of operations from the ‘other’ connection whilst we’re processing operations from the main connection. For example. If we’re in the read completion handler for a connection and we issue a read on another connection and that read completes immediately, inline, then we would begin to handle the completion and end up in the read completion handler for the other socket. This could cause issues with lock inversions if each connection needs to take out locks. The new default is to NOT handle the inline completions for the ‘other’ socket inline but instead to queue them until after the current socket’s operation handler completes. You can revert to the old behaviour by setting these to 1 in your Config.h file.
  • Added JETBYTE_DUMP_NAMED_INDEX_DETAILS_ON_LOCK which defaults to 0 and when set causes the names of named indices to be dumped to the default debug trace log when the indices are locked for the first time. This can be useful in tracking down mismatches between different named index providers.
  • Changed JetByteTools::Win32::ICreateMiniDumps::GenerateDumpFileName() so that it takes a ’type’ which, if it’s not an empty string, is added into the generated name just after the filename base portion. This allows you to group dumps by type - for situations where a you are generating dumps for different reasons.
  • Changed JetByteTools::Win32::CMiniDumper to take into account the changes to JetByteTools::Win32::ICreateMiniDumps::GenerateDumpFileName(). This means changing JetByteTools::Win32::CMiniDumper::CreateMiniDump(), JetByteTools::Win32::CMiniDumper::CreateMaxiDump() and JetByteTools::Win32::CMiniDumper::CreateFullDump() so that they take the ’type’ name and adding JetByteTools::Win32::CMiniDumper::CreateMiniDumpWithFileName(), JetByteTools::Win32::CMiniDumper::CreateMaxiDumpWithFileName() and JetByteTools::Win32::CMiniDumper::CreateFullDumpWithFileName() to disambiguate certain call signatures.
  • Changed JetByteTools::Win32::CMiniDumpGenerator to take into account the changes to JetByteTools::Win32::ICreateMiniDumps::GenerateDumpFileName(). This means changing JetByteTools::Win32::CMiniDumpGeneratorGenerateDumpHere() and JetByteTools::Win32::CMiniDumpGenerator::GenerateDump() to take the new ’type’ name and changing the bool used allow calls to ignore dump limits to an enum.
  • Added the concept of ‘per type’ mini dump limits. These can be set through JetByteTools::Win32::CMiniDumpGenerator::SetMaxDumps() by specifying a type string to set the maximums for. If a per type limit is not set then the global limit is used.
  • Added a new enum value to the JetByteTools::Win32::CMiniDumpGenerator::MaxDumpLimits enum to enable the use of ‘per type’ limits.
  • Changed JetByteTools::Win32::CGlobalErrorHandler to take into advantages of the dump ’type’ changes to categorise the types of dumps produced.
  • Cosmetic changes to JetByteTools::Win32::CThread to adjust the optional thread name tracking structure.
  • Added JetByteTools::Win32::CPerThreadErrorLog which can be instantiated on a thread to install handlers for std::terminate and std::unexpected. These handlers are per thread. Note that you should still use JetByteTools::Win32::CGlobalErrorHandler on the main thread as this also installs some process-wide handlers.
  • JetByteTools::Win32::CGlobalErrorHandler now derives from JetByteTools::Win32::CPerThreadErrorLog.
  • The signature for the constructor of JetByteTools::Win32::CSEHException::Translator has been changed to take an int which is not used for anything except to allow you to locate ‘old’ instances of the class and update them to instances of JetByteTools::Win32::CPerThreadErrorLog which include the functionality of the exception translator. This change can be turned off by defining JETBYTE_BREAK_SEH_EXCEPTION_TRANSLATOR_COMPATABILITY to 0 in config.h.
  • Added JETBYTE_INSTALL_PER_THREAD_ERROR_HANDLER_IN_CTHREAD which defaults to 1 and when set installs a JetByteTools::Win32::CPerThreadErrorLog object onto all JetByteTools::Win32::CThread object’s threads.
  • All threads created by framework code will install an instance of JetByteTools::Win32::CPerThreadErrorLog whether or not JETBYTE_INSTALL_PER_THREAD_ERROR_HANDLER_IN_CTHREAD is defined as 0.
  • Mini dumps created by JetByteTools::Win32::CCrtReportHook are now always created even if any program limits on the number of dumps to create has been met or exceeded.
  • Added JetByteTools::Win32::IIOCPWorkerThreadCallback::ProcessEx() which can be overridden to do the work that JetByteTools::Win32::IIOCPWorkerThreadCallback::Process() would do and then return a bool to indicate if you need to be informed when the queue has no more items to process. The default implementation simply calls JetByteTools::Win32::IIOCPWorkerThreadCallback::Process() and returns false.
  • Added JetByteTools::Win32::IIOCPWorkerThreadCallback::NoItemsToProcess() which is called once when the queue becomes empty if the last call to JetByteTools::Win32::IIOCPWorkerThreadCallback::ProcessEx() or JetByteTools::Win32::IIOCPWorkerThreadCallback::NoItemsToProcess() returned true. The default implementation simply returns false. Note that returning true will cause the queue to be checked again and if still empty for JetByteTools::Win32::IIOCPWorkerThreadCallback::NoItemsToProcess() to be called again.
  • Adjusted how services shut down in error situations when the service has failure actions set. When failure actions are enabled for a service we will now shut down in such a way that they are triggered. This involves terminating the thread that called StartServiceCtrlDispatcher() and making sure that we don’t call SetServiceStatus() with a status of SERVICE_STOPPED. We shut down normally if the service is in the process or starting up or shutting down when the error occurs so that we avoid the SCM repeatedly restarting a service that we can’t shut down. If “Enable actions for stops with errors” is set then the SCM will restart the service if it returns a non-zero exit code, even if it calls SetServiceStatus() with a status of SERVICE_STOPPED and there’s no way for us to prevent it restarting a service that is failing during init or shutdown.
  • JetByteTools::WebSocket::CHeaders can now handle adding headers with no value.