Re: LWLock deadlock and gdb advice

From: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
To: Andres Freund <andres(at)anarazel(dot)de>
Cc: Jeff Janes <jeff(dot)janes(at)gmail(dot)com>, Peter Geoghegan <pg(at)heroku(dot)com>, pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: LWLock deadlock and gdb advice
Date: 2015-07-29 11:55:54
Message-ID: 55B8BF4A.7020806@iki.fi
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On 07/29/2015 02:39 PM, Andres Freund wrote:
> On 2015-07-15 18:44:03 +0300, Heikki Linnakangas wrote:
>> Previously, LWLockAcquireWithVar set the variable associated with the lock
>> atomically with acquiring it. Before the lwlock-scalability changes, that
>> was straightforward because you held the spinlock anyway, but it's a lot
>> harder/expensive now. So I changed the way acquiring a lock with a variable
>> works. There is now a separate flag, LW_FLAG_VAR_SET, which indicates that
>> the current lock holder has updated the variable. The LWLockAcquireWithVar
>> function is gone - you now just use LWLockAcquire(), which always clears the
>> LW_FLAG_VAR_SET flag, and you can call LWLockUpdateVar() after that if you
>> want to set the variable immediately.
>>
>> This passes make check, but I haven't done any testing beyond that. Does
>> this look sane to you?
>
> The prime thing I dislike about the patch is how long it now holds the
> spinlock in WaitForVar. I don't understand why that's necessary? There's
> no need to hold a spinlock until after the
> mustwait = (pg_atomic_read_u32(&lock->state) & LW_VAL_EXCLUSIVE) != 0;
> unless I miss something?
>
> In an earlier email you say:
>> After the spinlock is released above, but before the LWLockQueueSelf() call,
>> it's possible that another backend comes in, acquires the lock, changes the
>> variable's value, and releases the lock again. In 9.4, the spinlock was not
>> released until the process was queued.
>
> But that's not a problem. The updater in that case will have queued a
> wakeup for all waiters, including WaitForVar()?

If you release the spinlock before LWLockQueueSelf(), then no. It's
possible that the backend you wanted to wait for updates the variable's
value before you've queued up. Or even releases the lock, and it gets
re-acquired by another backend, before you've queued up.

Or are you thinking of just moving the SpinLockRelease to after
LWLockQueueSelf(), i.e. to the other side of the "mustwait = ..." line?
That'd probably be ok.

- Heikki

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Andres Freund 2015-07-29 12:00:16 Re: pg_basebackup and replication slots
Previous Message Michael Paquier 2015-07-29 11:51:43 Re: Don'st start streaming after creating a slot in pg_receivexlog