2

I have a class that implements singleton pattern as you can see below:

public class SearchSingletonObject
{
    private static SearchSingletonObject foundation = null;
    public SearchObject Object= null;
    private static StringCollection views = null;
    private static object control = new object();
    public IEnumerable<string> blacklist = null;
    public static void ClearFoundation()
    {
        foundation = null;
    }
    public static SearchSingletonObject Foundation
    {
        get
        {
            if (foundation == null)
            {
                lock (control)
                {
                    if (foundation == null)
                    {

                        foundation = new SearchSingletonObject();
                        var blacks = File.ReadAllText(HostingEnvironment.ApplicationPhysicalPath + "\\blacklist.txt");
                        foundation.blacklist = blacks.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).Where(x => !string.IsNullOrEmpty(x) || x != " ");
                        views = new StringCollection();
                        var items = ConfigurationManager.AppSettings["SearchView"].Split(',');
                        foreach (var item in items)
                        {
                            views.Add(item);
                        }
                        foundation.Object = new SearchObject(ConfigurationManager.AppSettings["ContentDistributor"],
                                                                ConfigurationManager.AppSettings["Port"],
                                                                views);
                    }
                }
            }
            return foundation;
        }
    }
    public SearchSingletonObject()
    {

    }
}

We're using this class in our wcf rest services. But in non-periodic intervals we get "Value can not be null" errors. Here is my log file:

08.03.2011 11:40:39 ERROR Message : Value cannot be null.
Parameter name: source

StackTrace : at System.Linq.Enumerable.Where[TSource](IEnumerable`1 source, Func`2           predicate)
at Search.Service.SearchService.Search(String keyword, Int32 offset, Int32 hit, String navstate, String username, Boolean issecure, Int32 suggest, String sortref, String fields, Int32 IsFirstSearch, String misspelled, String category) in D:\tfs\Hey\HeyRestApi\HeyService\HeyService.cs:line 68

Log file mentions the row below in my service:

var blacks = SearchSingletonObject.Foundation.blacklist.Where<string>(x => item.Equals(x)).FirstOrDefault();

It seems strangely the "blacklist" object getting null value. After the error, we have to reset IIS, to get application working. We can not reproduce the error on our local servers. It just happens in our customers production environment.

How can we solve that problem and what can be the reason of this strange error?

Thanks in advance,

Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
xkcd
  • 2,538
  • 11
  • 59
  • 96
  • Why not avoid the pattern altogether? See http://stackoverflow.com/questions/162042/are-there-any-viable-alternatives-to-the-gof-singleton-pattern – TrueWill Mar 08 '11 at 13:52

1 Answers1

2

Double-checked locking is broken.

Short explanation:

Even if foundation is non-null, without a lock you can't be sure that foundation's members are non-null from the point of view of your processor.

You need to remove the if statement that's outside the lock.

Update

A better solution is to mark foundation as volatile:

private static volatile SearchSingletonObject foundation = null;

The need for volatile modifier in double checked locking in .NET has more details.

Community
  • 1
  • 1
arx
  • 16,686
  • 2
  • 44
  • 61
  • Thanks for your persuasive answer arx. Tonight we will publish our services in the way you told. – xkcd Mar 08 '11 at 13:02
  • The pattern is broken in Java, and for Java specific reasons. This is C#, on .NET so this doesn't answer the question. – Krzysztof Kozmic Mar 08 '11 at 13:23
  • 1
    It's broken in Java and it's broken in C#. More details here: http://stackoverflow.com/questions/1964731/the-need-for-volatile-modifier-in-double-checked-locking-in-net – arx Mar 08 '11 at 13:34