As I said a while ago, Visual Studio 2015 appears to have lots of pretty serious bugs.

One that probably bites me more than many people is this Save As bug. If you have a project and you select a file in that project and do a "Save As" such that the target file is also in the project then the VS2015 IDE crashes.

I tweeted about this a while back, and the Visual Studio Program Manager, Cathy Sullivan, wanted me to create a new project and see if the problem happened with it... Not quite sure why she couldn't do this herself, but anyway, here's a zip of a project created with VS2015 where there's a file called SaveMeAsTargetver.h. If you save that file as targetver.h then the IDE crashes.

Latest release of The Server Framework: 6.6.3

| 0 Comments
Version 6.6.3 of The Server Framework was released today.

This release is mainly a bug fix release but it also adds support for Visual Studio 2015 and Windows 10 (though we don't explicitly use any Windows 10 APIs). There are quite a lot of small changes due to us running Gimpel Lint over the code. Most of the changes will have fixed potential issues rather than issues that have actually been reported.

However, there are two serious fixes for the SChannel Option Pack for an issue that was introduced in Release 6.6.2 and which could cause corruption of the data flow in some situations and stalling and CPU pegging in another. There is also a fix which may prevent UDP datagram corruption, See here for more details.

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

All clients using Release 6.6.2 of the SChannel Option Pack are advised to upgrade to this release.

Bug fixes:

  • JetByteTools::IO::CBuffer::Clear() which now correctly sets m_ioSize to zero.
  • JetByteTools::IO::CBufferList::BufferData so that it cannot access pBuffer before it's initialised.
  • JetByteTools::IO::CLockableBufferProcessor::~CLockableBufferProcessor() to remove potential buffer leak.
  • JetByteTools::IO::CAsyncFileReader where we were checking the validity of data response flags incorrectly.
  • JetByteTools::SSPI::SChannel::CAsyncConnector::PerformWrite() where we could sometimes send invalid data.
  • JetByteTools::SSPI::SChannel::CAsyncConnector where we could sometimes get stuck in an infinite loop if we had decrypted data available but no application level read pending.
  • JetByteTools::Service::CService::ServiceMain() so that we set and clear the m_serviceStarting flag correctly.
  • Fix to all WSASend() and WSARecv() calls to prevent multiple threads from calling into the API on the same socket at the same time. See here for more details.
  • JetByteTools::Win32::CCallbackTimerWheel::EndTimeoutHandling() where we were leaking one shot timers.
  • JetByteTools::Win32::CThreadPool::OnThreadPoolThreadStopped() and JetByteTools::Win32::CThreadPoolEx::OnThreadPoolThreadStopped() so that the call to the monitor's OnThreadPoolStopped() function is consistent and in the right place.
  • JetByteTools::Win32::CSmartHandle to deal with closing pseudo thread or process handles.
  • Fix to JetByteTools::Socket::CFilterDataBase to ensure that each filter knows how many writes it has issued and that they pass completions to the next layer when they should.
  • JetByteTools::Win32::TReusableIdManager::InternalTryFree() so that we now correctly merge intervals. Note that this bug was purely in the way we stored the intervals (which was less efficient than it could be) and did not affect the function of the manager.
  • JetByteTools::Win32::TZeroInitialiseExpandableBuffer::Resize() so that it doesn't trash memory if you reduce the size of the buffer.
  • JetByteTools::Win32::TZeroInitialiseExpandableBuffer a fix to the assignment operator so that it actually compiles and works.

Changes:

  • Ran Visual Lint using Gimpel PC Lint on all code and adjusted to remove warnings and fix bugs.
  • Added support for Visual Studio 2015.
  • Removed all use of exception specifications. We only ever used throw() but that's now gone too.
  • Protected non-virtual destructors on interfaces are now virtual even though they you can't delete the object via the interface.
  • All destructors that could throw exceptions now have optional "log and swallow" exception handlers which are enabled by default. This is better than ignoring the problem and being faced with a call to std::terminate() which can be hard to track down.
  • Changed JetByteTools::IO::CNonPooledBuffer so that it doesn't have to be immutable. You can now create a non-pooled buffer and add data to it after creation.
  • Added JetByteTools::IO::CBufferChain::AvailableSpace() and JetByteTools::IO::CBufferChain::HasAvailableSpace()
  • Added JetByteTools::IO::CBufferChain::RemoveAsSingleBuffer() which will either consolidate a chain into the first buffer (if all the data will fit) or create a JetByteTools::IO::CNonPooledBuffer of the required size and return the data inthe new buffer.
  • Added the concept of a "purge handler" for buffer chains. This comes in the form of an interface JetByteTools::IO::CBufferChain::IHandlePurgedBufferRelease and a new override for JetByteTools::IO::CBufferChain::Purge which takes a purge handler and some user data. If the new version of purge is called the purge handler is called for each buffer purged from the chain and it is responsible for disposing of the purged buffer, normally by calling Release() on it. The reason for this is that it's now possible to have a buffer chain of buffers which are 'detached' buffer chains. When purge is called in this situation a purge handler can now be supplied which recreates the buffer chains and, in turn, purges them.
  • Added new constructors for JetByteTools::IO::CAsyncFileWriter and JetByteTools::IO::CAsyncFileWriterEx that take a filename and a JetByteTools::Win32::CSmartHandle to an open file.
  • Changed constructor for JetByteTools::IO::CAsyncFileWriter that previously took a HANDLE to take a JetByteTools::Win32::CSmartHandle
  • Added JetByteTools::IO::CBufferAllocator::GetNumActive() and JetByteTools::IO::CBufferAllocator::GetNumPooled()
  • Added explicit support for building against OpenSSL libs built with VS2015 as previous versions are no longer link compatible. Note that these #pragma link lines assume our internal naming convention for OpenSSL libs.
  • Added JetByteTools::IO::CBufferChain::Detach(), JetByteTools::IO::CBufferChain::Attach() and JetByteTools::IO::CBufferChain::Splice(). These allow you to take a buffer chain and 'detach' it from the buffer chain object so that you can work in terms of a single buffer (with the additional buffers chained on in the normal way but inaccessible). You can then take such a buffer and 'attach' it back to a buffer chain object. This allows you to pass a buffer chain through an interface which only understands single buffers. Splice() allows you to take an existing buffer chain and add a 'detached' buffer chain to the end of it.
  • Changed the number of tabs used in the JetByteTools::Service::CServiceManager::GetExtraHelp() message so that the remove option lines up correctly. I think this may be a dialog font issue and it may be inconsistent on different platforms.
  • Added JetByteTools::Win32::CActivatableObject::CommandWrapper to remove duplication in the users of JetByteTools::Win32::CActivatableObject
  • Removed JetByteTools::Win32::CFileChangeMonitor as it was not used or compiled. The functionality is contained in JetByteTools::Win32::CDirectoryChangeMonitor.
  • Added JetByteTools::Win32::CNTPTime which converts SYSTEMTIME to and from NTP timestamps.
  • Changes to the various JetByteTools::Win32::ToString() implementations so that they remain consistent across Visual Studio versions. Visual Studio 2015 changes how precision is used in the printf family of functions and provides greater default precision. We limit precision to 17 in JetByteTools::Win32::ToString() so that the output is consistent with earlier versions of Visual Studio.
  • JetByteTools::Win32::TReusableIdManager::Release() now returns the id.
  • JetByteTools::Win32::CCommandLine::Parse() now takes a reference to a string that can be used to return an error message.
  • Added JetByteTools::Win32::IQueueTimers::SetTimerWithRefCountedTimer(), JetByteTools::Win32::IQueueTimers::CancelTimerWithRefCountedTimer() and JetByteTools::Win32::IQueueTimers::DestroyTimerWithRefCountedTimer() which deal with the common pattern of code required when the timer handle is a reference counted class.
  • Added JetByteTools::Win32::IQueueTimers::RefCountedTimer.
  • Added JetByteTools::Win32::IManageEnvironmentVariables::TryDeleteVariable().
  • Added locking to JetByteTools::Win32::CEnvironmentBlock so that it's now safe to use from multiple threads.
  • Added checking when we lock JetByteTools::Win32::TLockableObjectPotentialOwner<> and JetByteTools::Win32::TReentrantLockableObjectPotentialOwner<> so that an exception is thrown if it's already locked. Also changed how JetByteTools::Win32::TReentrantLockableObjectPotentialOwner<> is implemented as it was unnecessarilly complex.
  • Breaking Change VS2015's exponent doesn't include a leading 0 when calling sprintf, etc. This changes the output for some calls to JetByteTools::Win32::ToString() and makes it inconsistent with all previous releases.

As usual I have used VMs to play with the CTP releases for the new version of Visual Studio and fixed up new warnings and build failures in my source so that I'm not too surprised when the RTM comes along.

Unfortunately as soon as I put VS2015 RTM on my build server and started running it as part of my CI system I started noticing strange things...

The first is that it seems to be possible to get VS2015 into a state where it will refuse to load C++ projects. I've no idea how I've managed this, but it's now happened twice. Rebooting the machine seems to fix things. The log file that the failure indicates might help shows that it's trying to load a the "Visual Studio C++ Project System Package" and it's getting an E_POINTER result...

The second issue seems to be a race condition in shutting down the new process that's used to help various parts of VS communicate with each other, VSHub.exe. My CI system will fire up a Visual Studio instance to build a project using /build and once that completes another project is likely to get built, sometimes two VS2015 builds will follow one another, other times there are other versions of Visual Studio building in between. VS 2015 appears to start an instance of VSHub.exe but only if one isn't running (or, more likely, it always starts one but if one's already running then the new ones shut down). Then when the last instance of VS quits VSHub.exe hangs around for a moment and then shuts down... It seems to crash if it's shutting down when a new instance of VS2015 is started (and, presumably decides that the VSHub.exe that is shutting down is the one to use). A fix for this issue is simply to keep VSHub.exe alive for the entire time that all VS2015 builds need to run and I can do this by having an instance of VS2015 open on the build machine whilst the CI system is running...

Thanks to Abe10, in this thread, for the workaround for the VSHub.exe issue.

6 out of 10 for this VS release Microsoft, try harder. I hope the Windows 10 team have better QA.

I now have a real solution to the problem that I outlined on Saturday night and this solution, unlike the one developed during my "Macallan driven development" session on Saturday evening actually works.

The problem is that when using code to run build using VS2010 by running a project into devenv.com I get the following error message:

C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\CodeAnalysis\Microsoft.CodeAnalysis.targets(214,5): error MSB4175: The task factory "CodeTaskFactory" could not be loaded from the assembly "C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Build.Tasks.v12.0.dll". Could not load file or assembly 'file:///C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Build.Tasks.v12.0.dll' or one of its dependencies. The system cannot find the file specified.

The project builds correctly from the command window using the exact same command line as I use in my calls to CreateProcess().

I was on the right track on Saturday evening. It is an environment issue, just not the one that I thought it was. I also now understand why I thought I'd solved the problem on Saturday night only to discover that the fix didn't work when I checked it again on Sunday morning.

The problem is caused by the presence of "VisualStudioVersion" in the environment. This variable is set to 12.0 when my task runner program is run from within VS2013 either when debugging or running without the debugger attached but launching from within VS2013. The presence of this variable in the task runner's environment somehow causes VS2010 to use the latest version of MSBuild that ships with VS2013. When doing this MSBuild gets confused about which .Net framework directory to load assemblies from and fails to locate its dll. Removing the "VisualStudioVersion" from the inherited environment before launching VS2010 programatically fixes the problem.

Running my task running from a normal command prompt, rather than from inside of VS2013, allows it to work correctly without needing to remove the variable (as the variable is only added by VS2013 itself). I expect that I tested like this on Saturday night and that's what made me think I'd solved the problem them.

VS2013 actually adds several "VisualStudio" variables to the environment and I now remove all of them before running any task from my task runner.

Updated: 12 July 2015 - It seems that this is all incorrect... Upon running my tests again this morning I find that the x64 task runner also fails to run VS2010 correctly and so the environment differences are unlikely to be the cause...

So, having decided that my continuous integration system could be better, and having looked at JetBrains' TeamCity and decided that it doesn't quite fit I'm looking back at some code that I wrote back in 2008 when I last thought about this kind of thing...

I have some code which works with trees of dependant tasks and triggers sub tasks once the tasks they depend on complete successfully. The code uses CreateProcess() and Win32 Jobs to control the tasks and it can run builds and tests using the various flavours of Visual Studio installed on the box in question.

So far, so good as a starting point for an agent that can run multiple builds on a machine...

My problem, well, one of them, being that when using VS2010 by running a project into devenv.com I get the following error message:

C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\CodeAnalysis\Microsoft.CodeAnalysis.targets(214,5): error MSB4175: The task factory "CodeTaskFactory" could not be loaded from the assembly "C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Build.Tasks.v12.0.dll". Could not load file or assembly 'file:///C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Build.Tasks.v12.0.dll' or one of its dependencies. The system cannot find the file specified.

This is annoying, to say the least, VS2005, 2008 and 2012 and 2013 all work fine, it's just 2010 that fails. I googled the issue and the general consensus is that once you've installed VS2013 a different version of MSBuild is used. Of course that doesn't answer the question of why it 'works on my machine' except when my task runner is running the command...

Eventually I got the task runner to dump the environment and did the same from the command prompt where the command worked. The difference being that the command prompt that worked had an 'x64' environment and the task runner had a different, 'x86/win32' environment... This was because the task runner was a Win32 process. Running the task runner as x64 fixed the issue. So there's probably a bug in the VS2013 installation code that fails to set some environment variables for the Win32 command prompt that are required once it's "screwed with" the existing MSBuild installation on the box...

I'm expecting that manually adding the missing bits to the 'x86' environment will mean that the task runner will work as a Win32 build AND an x64 build...

Bug hunting

| 0 Comments

I've just spent a day tracking down a bug in a pending release of The Server Framework. It was an interesting, and actually quite enjoyable, journey but one that I shouldn't have had to make. The bug was due to a Windows API call being inserted between the previous API call and the call to GetLastError() to retrieve the error code on failure. The new API call overwrote the previous error value and this confused the error handling code for the previous API call. This was a bit of a "school boy error" and it was made worse by the fact that the code in question had a comment which clearly explained why nothing should be placed between the API call and the call to GetLastError().

Back in September I mentioned that I had found a problem with my usage of Slim reader/writer locks. I expected this to be something that I was doing wrong but it turned out that it was a kernel bug.

This morning Johan Torp tweeted that a hotfix for this issue is now available.

The note on the hotfix states: "Note These issues are not obvious and are difficult to debug. This update is intended for applicable systems to apply proactively in order to increase the reliability of these systems.", so go install it even if you don't know that you're having these problems right now...

Video streaming from IoT devices

| 0 Comments

As I mentioned back in February I've been working on a custom video streaming solution for one of my clients. This has been a lot of fun. It was a nicely defined spec using industry standard protocols developed on a fixed price basis with lots of TDD, what's not to like.

The system allows a controlling application to set up RTSP streams for broadcasting to multiple clients. The data for the stream is being transmitted live from one of thousands of smart (IoT) devices and the server buffers this and broadcasts it using RTSP to publish the RTP streams. The controller can also get the server to record these live streams to disk and play them back via an RTSP stream at a later date.

All of the streams are dynamic and the controlling app is responsible for making sure that the IoT devices know where to send their raw video feeds and also for communicating the RTSP urls that can be used to access the streams.

Although this system was written using our new Streaming Media Option Pack there was a lot of scope for new code to be written. Up until this point the option pack revolved around playing pre-recorded data from files. Broadcasting and recording live video required a bit more thought.

This system allows for thousands of concurrent streams and allows multiple users to view what otherwise would be a single raw H264 stream from the IoT device. The device can stay reasonably simple and the server system can add the complexity required for broadcasting and conforming with the required specs.

To enable development without needing access to the custom hardware that's under development I put together a simple app which chops up a video file and sends it in the format that the IoT devices will use, this massively simplified testing. Given the amount of TDD that was being done on the actual code the integration testing with the mock IoT device was pretty painless but it made it possible to test the server under load and also allowed for a simple demo system to be put together.

I'd forgotten quite how much I enjoy these 'perfect' development projects where the customer knows what they want and can communicate it clearly, the schedule is sensible, the challenge is taxing but not impossible and the price is right. Throw in the comfort of being able to 'waste' as much time as I like with TDD and the end result is a project which actually ends up being quite a calming and meditative experience.

And now back to the real world...

New IoT fixed-price development project

We're pleased to be working with one of our secretive security company clients again to provide a custom video streaming server for them. The server will enable them to record and stream live video from their network of "internet of things" connected devices.

As with all M2M and IoT projects this system needs to be able to scale to many thousands of concurrently connected devices and we're pleased to be able to use The Server Framework's new Streaming Media Option pack to be able to provide a complete solution quickly and cost effectively for our client.

That Slim Reader/Writer lock issue is a kernel bug

| 0 Comments
It looks like the Slim Reader/Writer issue that I wrote about back in September is a kernel bug after all.

Stefan Boberg has just tweeted to let me know that Microsoft has confirmed it's a bug and that a hot fix is in testing.

About this Blog

I usually write about C++ development on Windows platforms, but I often ramble on about other less technical stuff...

This page contains recent content. Look in the archives to find all content.

I have other blogs...

Subscribe to feed The Server Framework - high performance server development
Subscribe to feed Lock Explorer - deadlock detection and multi-threaded performance tools
Subscribe to feed l'Hexapod - embedded electronics and robotics
Subscribe to feed MegèveSki - skiing