Skip to content Skip to sidebar Skip to footer

Are Cookie Read/write Atomic In Browser

I am trying to implement a cross tab mutex for my needs. I found a implementation here. which seems quite promising. Basically, it implements Leslie Lamport's algorithm with nee

Solution 1:

Neither cookies, nor localStorage provide atomic transactions.

I think you might have misunderstood that blog post, it doesn't say that his implementation doesn't work in Chrome, it does not rely on localStorage providing atomic read/writes. He says that normallocalStorage access is more volatile in Chrome. I'm assuming this is related to the fact that Chrome uses a separate process for each tab, whereas most other browsers tend to use a single process for all tabs. His code implements a locking system on top of localStorage which should protect against things getting overwritten.

Another solution would be to use IndexedDB. IndexedDB does provide atomic transactions. Being a new standard it is not supported in as many browsers as localStorage, but it does have good support in recent versions of Firefox, Chrome and IE10.

Solution 2:

No. Even if the browsers probably implement a read and a write lock on the cookie it won't protect you from changes that happens between a read and a consequent write. This is easy to see by looking at the javascript API for cookies, there is no mutex functionality there...

Solution 3:

I ran into this concurrency issue using localStorage today (two years alter..)

Scenario: Multiple tabs of a browser (e.g. Chrome) have identical script code that gets executed, basically at the same time (called by e.g. SignalR). The code reads and writes to localStorage. Since the tabs run in different processes but access the shared local storage collectively, reading and writing leads to undefined results since a locking mechanism is missing here. In my case I wanted to make sure that only one of the tabs actually works with the local storage and not all of them..

I tried the locking mechanism of Benjamin Dumke-von der Ehe metioned in the question above but got undesired results. So I decided to roll my own experimental code:

localStorage lock:

Object.getPrototypeOf(localStorage).lockRndId = newDate().getTime() + '.' + Math.random();
Object.getPrototypeOf(localStorage).lock = function (lockName, maxHold, callback) {
    var that = this;
    var value = this.getItem(lockName);
    var start = newDate().getTime();    
    var wait = setInterval(function() {
        if ((value == null) || (parseInt(value.split('_')[1]) + maxHold < start)) {
            that.setItem(lockName, that.lockRndId + '_' + start);
            setTimeout(function () {
                if (that.getItem(lockName) == (that.lockRndId + '_' + start)) {
                    clearInterval(wait);
                    try { callback(); }
                    catch (e) { throw'exeption in user callback'; }
                    finally { localStorage.removeItem(lockName); }
                }
            }, 100);
        }        
    }, 200);        
};

usage:

localStorage.lock(lockName, maxHold, callback);

  • lockName - a global scope unique name for the lock - string
  • maxHold - the maximum time to protect the script in milliseconds - integer
  • callback - the function containing the script that gets protected

example: "only play a sound in one tab"

//var msgSound = new Audio('/sounds/message.mp3');localStorage.lock('lock1', 5000, function(){

    // only one of the tabs / browser processes gets here at a timeconsole.log('lock aquired:' + newDate().getTime());

    // work here with local storage using getItem, setItem// e.g. only one of the tabs is supposed to play a sound and only if none played it within 3 seconds        var tm = newDate().getTime();
    if ((localStorage.lastMsgBeep == null)||(localStorage.lastMsgBeep <tm-3000)) {
       localStorage.lastMsgBeep = tm;
       //msgSound.play();                       console.log('beep');                        
    }  
});

Post a Comment for "Are Cookie Read/write Atomic In Browser"