X-Recipient: archive-cygwin@delorie.com
DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id
	:list-unsubscribe:list-subscribe:list-archive:list-post
	:list-help:sender:date:from:to:subject:message-id:reply-to
	:references:mime-version:content-type:in-reply-to; q=dns; s=
	default; b=PU/mUv4knrq2xOQPgUDaL+mqczPOcFkiW2KMjK11oJx2ggGjAbDms
	ZPTT4bNQvzNW9mvGYFWP3mSHFVMwBjLoY2/KVd9TQX6qmLa+WPpVNEBkArNYECFb
	RPr0lsc+ksJwOg6HkIsbX+X4TjM0qcWbQ2De/fZBF/+HeThBAOYq04=
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id
	:list-unsubscribe:list-subscribe:list-archive:list-post
	:list-help:sender:date:from:to:subject:message-id:reply-to
	:references:mime-version:content-type:in-reply-to; s=default;
	 bh=KFO3SXi0rx+HMwWqkB6IP7vbtJQ=; b=TzE1wntLlShTpanp15Z363SrDCFH
	F5DbvlsMCkT/oDBzTG8ipnCy6W4GR7yVjot8umdI/kq8P5HVFcZUsX8QiZ95ZdxJ
	irqAeygdTaXoQtuRu4Tu2p5K9Lwc1dYfJxK312c1F4KC2Ts97+wcmFOVtSHumCHM
	dZiSvg4wWPbNfoo=
Mailing-List: contact cygwin-help@cygwin.com; run by ezmlm
List-Id: <cygwin.cygwin.com>
List-Subscribe: <mailto:cygwin-subscribe@cygwin.com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin@cygwin.com>
List-Help: <mailto:cygwin-help@cygwin.com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner@cygwin.com
Mail-Followup-To: cygwin@cygwin.com
Delivered-To: mailing list cygwin@cygwin.com
X-Spam-SWARE-Status: No, score=-1.8 required=5.0 tests=AWL,BAYES_00,TW_FC autolearn=ham version=3.3.1
Date: Thu, 6 Jun 2013 19:22:18 +0200
From: Corinna Vinschen <corinna-cygwin@cygwin.com>
To: cygwin@cygwin.com
Subject: Re: [TEST] sqlite3-3.7.17-1 (Cygwin 1.7.19 locking feature)
Message-ID: <20130606172218.GD13320@calimero.vinschen.de>
Reply-To: cygwin@cygwin.com
Mail-Followup-To: cygwin@cygwin.com
References: <51ACF886.10301@etr-usa.com> <51AD3BB4.2010601@acm.org> <20130604084128.GB19572@calimero.vinschen.de> <20130604093749.GA32667@calimero.vinschen.de> <51AF9A32.2030706@etr-usa.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline
In-Reply-To: <51AF9A32.2030706@etr-usa.com>
User-Agent: Mutt/1.5.21 (2010-09-15)

On Jun  5 14:06, Warren Young wrote:
> On 6/4/2013 03:37, Corinna Vinschen wrote:
> >
> >It would be nice to have a simple testcase (plain C, only Cygwin
> >POSIX calls, self-contained, yada yada) to see what sqlite expects in
> >POSIX lock mode.
> 
> SQLite locking is a hairball.  It is spread over a range of about
> 2.5 kLOC within the 140 kLOC sqlite3.c file, and those routines are
> behind about three layers of indirection from the mainline SQLite
> code.
> 
> Mind, I'm not talking about the *callers* of this code here, just
> the locking routines themselves.  Add in all the callers and *their*
> expectations and...well...<shudder>
> 
> I think we have to define the problem as "SQLite locking requires
> what SQLite requires today."
> 
> Luckily, while creating the -2 packages, I stumbled across a STC in
> SQL that replicates the reported problem:
> 
> $ ./sqlite3 foo.db 'create table fred(id integer, barney text)'
> $ CYGWIN_SQLITE_LOCKING=posixmand ./sqlite3 foo.db \
>   'insert into fred(barney) values("wilma")'

So, here's what happens.  The below list contains the lock requests
of sqlite up to the point where it fails.  "r" is a read lock request,
"w" a write lock request, "u" an unlock request.  The next two values
are the byte offset and byte length of the lock, the last is the
status code after calling the Windows Lock/Unlock function:

  A.  r 1073741824 1    STATUS_SUCCESS
  B.  r 1073741826 510  STATUS_SUCCESS
  C.  u 1073741824 1    STATUS_SUCCESS
  D.  u          0 0    STATUS_RANGE_NOT_LOCKED ==> STATUS_SUCCESS
  E.  r 1073741824 1    STATUS_SUCCESS
  F.  r 1073741826 510  STATUS_SUCCESS
  G.  u 1073741824 1    STATUS_SUCCESS
  H.  w 1073741825 1    STATUS_SUCCESS
  I.  w 1073741824 1    STATUS_SUCCESS
  J.  w 1073741826 510  STATUS_LOCK_NOT_GRANTED
  K.  r 1073741826 510  STATUS_SUCCESS
  L.  u 1073741824 2    STATUS_RANGE_NOT_LOCKED ==> STATUS_SUCCESS
  M.  u          0 0    STATUS_RANGE_NOT_LOCKED ==> STATUS_SUCCESS

There are two problems:

The lazy unlock request D tells the system to unlock all locks on the
entire file.  This works fine with POSIX locks, but it does not work
with Windows locks.  These require to unlock a lock exactly as it has
been created.  This means, after this unlock, the "r 1073741826 510"
lock is still present.  Since a failed unlock practically doesn't exist
on POSIX, Cygwin converts STATUS_RANGE_NOT_LOCKED to STATUS_SUCCESS,
so fcntl returns 0, success.  Same for L and M, with L failing
because the call tries to use a single unlock on a range holding two
locks.  The locks would have to be unlocked each by itself.

Ultimately the write lock request J fails, because there are already
the read locks B and F present.  POSIX and BSD locks can simply
replace another lock in the same spot if the existing lock is hold
by the same process (POSIX) or file object (BSD).  Windows locks
add up, and require to unlock all locks in the same area before
allowing another lock type to be placed.  No atomic replacement of an
existing read lock with a write lock or vice versa.

In theory this scenario could be worked around in Cygwin by bookkeeping
the present locks, plus a piece of code which unlocks all existing locks
in the given range when a lock or unlock request is coming in.  However,
the really dismal fact is, that an unlock before a lock would never be
atomic.  If the F_SETLK request unlocks an existing lock and then
another process gets a lock in the requested range, the first process
ends up with a failed fcntl call and no lock at all.


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

