Why use static analysis? Exploring an error from Akka.NET
Tags: csharp, dotnet, opensource, programming
Published: 2022-04-25 13:25:45

![0940_AkkaNET_Error/image1.png](https://import.viva64.com/docx/blog/0940_AkkaNET_Error/image1.png)

> Use static analysis regularly, not just before releases\.\.\.
> The earlier you find errors, the cheaper they are to fix\.\.\. 

You probably heard this a hundred times\. Today we'll answer the "Why?" question once again\. An error from the Akka\.NET project will assist us\. 

**The error**

We'll start with a task\. Find a defect in the code below:

```csharp
protected override bool ReceiveRecover(object message)
{
  switch (message)
  {
    case ShardId shardId:
      _shards.Add(shardId);
      return true;
    case SnapshotOffer offer when (offer.Snapshot is 
                                   ShardCoordinator.CoordinatorState state):
      _shards.UnionWith(state.Shards.Keys.Union(state.UnallocatedShards));
      return true;
    case SnapshotOffer offer when (offer.Snapshot is State state):
      _shards.Union(state.Shards);
      _writtenMarker = state.WrittenMigrationMarker;
      return true;
    case RecoveryCompleted _:
      Log.Debug("Recovery complete. Current shards [{0}]. Written Marker {1}", 
                string.Join(", ", _shards), 
                _writtenMarker);

      if (!_writtenMarker)
      {
        Persist(MigrationMarker.Instance, _ =>
        {
          Log.Debug("Written migration marker");
          _writtenMarker = true;
        });
      }
      return true;
    case MigrationMarker _:
      _writtenMarker = true;
      return true;
  }
  ....
}
```

Let's examine the code above and see what the problem is\.

The `_shards` variable is of type `HashSet<ShardId>`\. The code above calls several methods that change the state of this set\.

`HashSet<T>.Add`:

```csharp
_shards.Add(shardId);
```

`HashSet<T>.UnionWith`: 

```csharp
_shards.UnionWith(state.Shards.Keys.Union(state.UnallocatedShards));
```

However, one of these calls is incorrect: 

```csharp
_shards.Union(state.Shards);
```

It does not change the state of the `_shards` object\. `Enumerable.Union` is a LINQ extension method that does not change the original collection and returns a modified collection instead\. This means, the method call's result must be saved somewhere or used somehow\. We do not see that in the code\.

The PVS\-Studio analyzer issued the following warning: *V3010 The return value of function 'Union' is required to be utilized\. Akka\.Cluster\.Sharding EventSourcedRememberEntitiesCoordinatorStore\.cs 123*

By the way, here's what the fixed code looks like:

```csharp
_shards.UnionWith(state.Shards);
```

**How we found the error — or talk number 101 on the benefits of static analysis**

Every night our server runs static analysis for several open\-source projects\. These include Akka\.NET\. Why do we do it? This practice offers a few benefits:

* it provides an extra way to test the analyzer;
* it helps us write notes like this one and provides us with interesting examples that demonstrate the benefits of static analysis\.

We wrote more about it [here](https://pvs-studio.com/en/blog/posts/cpp/0799/)\.

And now a few words on our case at hand — how the error appeared and how it was fixed\.

*April 20, 2022:*

* code with an error is [committed](https://github.com/akkadotnet/akka.net/commit/2cbdbcbd07ac65596a8a38eb30e54ba22041d1b1)  to the Akka\.NET project's dev branch \(a [link](https://github.com/akkadotnet/akka.net/blob/8e7f02149451856c9160f9cd28d687ff8a166a11/src/contrib/cluster/Akka.Cluster.Sharding/Internal/EventSourcedRememberEntitiesCoordinatorStore.cs#L123) to the specific line of code\);

*April 21, 2022:*

* our server analyzes the code and sends me an email with warnings;
* I investigate the problem and create an [issue](https://github.com/akkadotnet/akka.net/issues/5862) on GitHub;
* the developers fix the error\. A [link](https://github.com/akkadotnet/akka.net/pull/5863/commits/263a459e11e4d1a273819b728f0dcc5cb7320934) to the commit\.

I think that was some pretty smooth collaboration\! Thanks to the developers for the prompt fix\.

And now to the important question — how long would this error have existed in the code if events had taken a different turn? Here I'll leave some room for your imagination\.

**So what can you do right now to avoid mistakes like this one?**

* Use a static analyzer\. You can download one [here](https://pvs-studio.com/pvs_akka_)\. Remember to use the *pvs\_akka* promo code — then, instead of 7 days, the trial license will work 30 days\.
* If you want to read more articles and notes like this one, [follow](https://twitter.com/_SergVasiliev_) me on Twitter\.