X-Recipient: archive-cygwin AT delorie DOT com X-Spam-Check-By: sourceware.org Date: Sun, 26 Feb 2012 13:57:35 +0100 From: Corinna Vinschen To: cygwin AT cygwin DOT com Subject: Change in flock(2), testers welcome Message-ID: <20120226125735.GM7755@calimero.vinschen.de> Reply-To: cygwin AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Hi folks, Cygwin's flock(2) implementation is far from ideal. While it seems to work mostly in 1.7.11 now, it has a wide-open definition leak: BSD locks created by the flock(2) call are bound to a file descriptor. Consider this situation: - process 1 opens a file and forks process 2 - process 2 calls flock on the inherited descriptor and forks process 3 - Since the descriptor is shared between all three processes, the lock is basically hold by all three processes. Any one of them can call flock again to unlock the file. And there's the problem in Cygwin so far. While a child process inherits a lock on a file, this is not the case with parent processes. So, in Cygwin, process 2 and 3 share the lock, but process 1 is entirely ignorant of the lock. The most important result is that this usage of the flock(1) tool (taken from the Linux man page) does not work correctly in Cygwin: ( flock -n 9 || exit 1 # ... commands executed under lock ... ) 9>/var/lock/mylockfile This works, because the parent shell of the flock tool inherits the lock from the flock(1) tool, so the sibling commands of flock also inherit the lock and the entire process group is holding the lock. I think I have a solution for this scenario now. It's still not perfect, but at least it allows to push a lock to the parent process as well, so the above, typical usage of flock(1) should work. What the code does is to duplicate the object handle and inject a remote thread into the parent so it can do the bookkeeping. Same thing reverse when a lock is explicitely unlocked. Please note that this still doesn't work over more than one process levels. Only the immediate parent is notified of the lock. So something like this: ( ( flock -n 9 || exit 1 } # ... commands executed under lock ... ) 9>/var/lock/mylockfile doesn't work yet. Also, if the parent process is running under another user account and you're not an administrator account yourself, it will fail as well. I'm still looking for a solution which does not involve to keep a service like cygserver around... Anyway, I was mostly interested to find a solution for this typical usage of flock(1) for now. For those interested in this stuff, please give it a try. You'll find it in the latest snapshot I just uploaded to http://cygwin.com/snapshots/ Thanks, Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Project Co-Leader 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