LOCK_DEBUG is busted

From: Robert Haas <robertmhaas(at)gmail(dot)com>
To: pgsql-hackers(at)postgresql(dot)org, Bruce Momjian <bruce(at)momjian(dot)us>
Subject: LOCK_DEBUG is busted
Date: 2011-11-10 21:25:46
Message-ID: CA+TgmoYtB0o1rZX2aO6M8BgnKsZRyH7NeqSt9xR=yCpYW=LkLg@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

It's possible to compile the source tree with LOCK_DEBUG defined, but
the resulting postgres promptly dumps core, due to the fact that
user_lockmethod doesn't supply any value for trace_flag; thus, the
first LockReleaseAll(USER_LOCKMETHOD) dereferences a NULL pointer.
This is the result of the following commit:

commit 0180bd6180511875db046bf8ddcaa633a2952dfd
Author: Bruce Momjian <bruce(at)momjian(dot)us>
Date: Thu Oct 13 19:59:13 2011 -0400

Remove all "traces" of trace_userlocks, because userlocks were removed
in PG 8.2.

As far as I can see, that commit was just wrong and should be
reverted. I believe that Bruce's motivation for this commit was the
following sentence from the documentation:

- User locks were removed as of PostgreSQL version 8.2. This option
- currently has no effect.

The trouble with this is that it's just not true. With that commit
reverted and LOCK_DEBUG defined in pg_config_manual.h:

rhaas=# set trace_userlocks=1;
LOG: LockReleaseAll: lockmethod=2
STATEMENT: set trace_userlocks=1;
LOG: LockReleaseAll done
STATEMENT: set trace_userlocks=1;
SET
rhaas=# select pg_advisory_lock(300001,300001);
LOG: LockAcquire: lock [16384,300001] ExclusiveLock
STATEMENT: select pg_advisory_lock(300001,300001);
LOG: LockAcquire: new: lock(0x103ad37c0)
id(16384,300001,300001,2,8,2) grantMask(0) req(0,0,0,0,0,0,0)=0
grant(0,0,0,0,0,0,0)=0 wait(0) type(ExclusiveLock)
STATEMENT: select pg_advisory_lock(300001,300001);
LOG: LockAcquire: new: proclock(0x103b590b8) lock(0x103ad37c0)
method(2) proc(0x103d72b30) hold(0)
STATEMENT: select pg_advisory_lock(300001,300001);
LOG: LockCheckConflicts: no conflict: proclock(0x103b590b8)
lock(0x103ad37c0) method(2) proc(0x103d72b30) hold(0)
STATEMENT: select pg_advisory_lock(300001,300001);
LOG: GrantLock: lock(0x103ad37c0) id(16384,300001,300001,2,8,2)
grantMask(80) req(0,0,0,0,0,0,1)=1 grant(0,0,0,0,0,0,1)=1 wait(0)
type(ExclusiveLock)
STATEMENT: select pg_advisory_lock(300001,300001);
LOG: LockReleaseAll: lockmethod=2
STATEMENT: select pg_advisory_lock(300001,300001);
LOG: LockReleaseAll done
STATEMENT: select pg_advisory_lock(300001,300001);
pg_advisory_lock
------------------

(1 row)

Now, whether or not this facility is well designed is a worthwhile
question. Trace_lock_oidmin seems pretty sketchy to me, especially
because it's blindly applied to even to lock tags where the second
field isn't a relation - i.e. SET_LOCKTAG_TRANSACTION sets it to zero,
SET_LOCKTAG_VIRTUALTRANSACTION sets it to the localTransactionId,
SET_LOCKTAG_OBJECT sets it to the classId member of the objectaddress,
and advisory locks set it to 32 bits of the user's chosen locktag. So
by default, with trace_userlocks turned on and no other changes,
pg_advisory_lock(16384,0) produces output like that shown above and
pg_advisory_lock(16383,0) is met with silence. So maybe we should
just rip some or all of this stuff out instead of worrying too much
about it. If we're not going to do that, then we should revert the
above commit, so that it works again, at least as much as it did
before.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Robert Haas 2011-11-10 21:28:12 Re: type privileges and default privileges
Previous Message Bruce Momjian 2011-11-10 21:19:59 Re: foreign key locks, 2nd attempt