Writing

Feed Software, technology, sysadmin war stories, and more.

Tuesday, September 20, 2011

Multi-threaded unprotected accesses to static variables

I think I've found yet another way to make things go really loopy in multi-threaded programs. Consider some C++ code which looks like this:

static long num_foo = 0;
 
foo::foo() {
  num_foo++;
}
 
foo::~foo() {
  num_foo--;
}

static at that spot means there's only the one location. It seems that the author wants to keep track of how many instances of this class are in use. Exactly why isn't apparent, but there it is.

Now imagine what happens the first time this class is created or destroyed in one thread, and is also created or destroyed in another thread at the same time. You're looking at unprotected stores and loads against the same address on multiple processors! It should come as no surprise that Valgrind's DSD tool freaks out about this.

The worst part of this is that the real class which does this is used to pass messages around in an application which is massively parallel by design. These messages are created and destroyed constantly, so there are plenty of chances for races here.

Assuming this use count is even needed, it seems like having another class would be the way to go. Pass it in when creating a new foo, and let it call the counter on the way in and again on the way out. The counter class would do all of the usual mutex stuff to protect accesses. Easy!