This project is read-only.
1

Resolved

Not all of the awaiting reader locks informed when writer lock is released

description

In case we have a process holding write lock and few processes trying to acquire read lock (waiting for some timeout), only first one reader will be informed when writer lock will be released - it will acquire reader lock immediately and Group.ReadLock(string lockName, int timeout) will return true. Other awaiting processes will keep waiting until the timeout is expired and return false then.
However, you can try to call ReadLock() once again then and it will acquire reader lock immediately.
I'm not 100% sure it's an issue, but looks like all of the awaiting readers should be granted with reader lock, not only the first one.

P.S.
Vsync 2.2.2063.

P.S.2
I'm also was unable to find exact Vsync version number in source code, so probably it's worth to add it.

comments

birman wrote May 3, 2016 at 2:14 PM

Again, no problem, we can have a look.

The Vsync release number is in the comment at the top of the Vsync.cs file, on line 2. You would see something like this:
...
// <copyright file="Vsync.cs" company="Kenneth P. Birman">
// Vsync System, V2.2.$Rev: 2032 $, Developed by Kenneth P. Birman, (c) 2010 - 2016.
...

But as I look at this line (from the current release) it seems clear that something is wrong: SVN is clearly not updating it correctly. I'll need to check to see why that could be happening -- with $Rev$ SVN does a text substitution and should be updating this string automatically. Apparently it stopped doing so, but not very long in the past (2.2032 was a fairly recent release). Perhaps an SVN problem?

At any rate:

Ideally, a minimal example would have no lines of logic not actually required to cause the problem, plus of course instructions on precisely how to run it to see the issue occur.

konst3d wrote May 4, 2016 at 10:38 AM

Write-lock application:
using System;
using Vsync;

namespace WriteLockApp
{
    class Program
    {
        static void Main(string[] args)
        {
            VsyncSystem.Start();

            var group = new Group("group1");

            group.ViewHandlers += view =>
            {
                Console.WriteLine("Group view changed. Addres: {0}, rank: {1}, total: {2}, alive: {3}, failed: {4}.",
                    view.gaddr,
                    view.GetMyRank(),
                    view.GetMembers().Length,
                    view.GetLiveMembers().Length,
                    view.GetFailedMembers().Length);
            };

            group.Join();

            Console.WriteLine("Press enter to acquire write-lock.");
            Console.ReadLine();
            Console.WriteLine("Acquiring write-lock...");

            if (group.WriteLock("lock1", 5000))
            {
                Console.WriteLine("Write-lock acquired, press enter to release...");
                Console.ReadLine();
                group.Unlock("lock1");
            }
            else
            {
                Console.WriteLine("Failed to acquire write-lock.");
            }

            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();

            group.Leave();
            VsyncSystem.Shutdown();
        }
    }
}
Read-lock application:
using System;
using Vsync;

namespace ReadLockApp
{
    class Program
    {
        static void Main(string[] args)
        {
            VsyncSystem.Start();

            var group = new Group("group1");

            group.ViewHandlers += view =>
            {
                Console.WriteLine("Group view changed. Addres: {0}, rank: {1}, total: {2}, alive: {3}, failed: {4}.",
                    view.gaddr,
                    view.GetMyRank(),
                    view.GetMembers().Length,
                    view.GetLiveMembers().Length,
                    view.GetFailedMembers().Length);
            };

            group.Join();

            Console.WriteLine("Press enter to acquire read-lock.");
            Console.ReadLine();
            Console.WriteLine("Acquiring read-lock...");

            if (group.ReadLock("lock1", 5000))
            {
                Console.WriteLine("Read-lock acquired, press enter to release...");
                Console.ReadLine();
                group.Unlock("lock1");
            }
            else
            {
                Console.WriteLine("Failed to acquire read-lock.");
            }

            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();

            group.Leave();
            VsyncSystem.Shutdown();
        }
    }
}
Run 1 instance of write-lock app and 2 instances of read-lock app. Press enter in the write-lock app to acquire write-lock, then switch to read-locks apps, press enter to start read-lock acquisition, switch back to write-lock app, press enter to release it - watch only one of the read-lock apps will successfully acquire the lock, another one will wait until timeout is expired.

birman wrote May 4, 2016 at 6:53 PM

OK, this is a genuine bug. I've got a fix to it and will post it after more testing.

birman wrote May 4, 2016 at 7:51 PM

Fixed in V2.2.2095

konst3d wrote May 5, 2016 at 8:34 AM

Thanks a lot, I will be waiting for 2.2.2095.