[PATCH 2 of 4] cmdutil: replace unix pipe handshake with file lock

Patrick Mezard pmezard at gmail.com
Sun Jan 10 11:33:01 CST 2010


# HG changeset patch
# User Patrick Mezard <pmezard at gmail.com>
# Date 1262808718 -3600
# Node ID 5b7842ed06260749364e7f71dc1fcf6f6df653d2
# Parent  46c105dcbc105bd9fed00adb38f92dbba4e4a883
cmdutil: replace unix pipe handshake with file lock

The pipe handshake cannot be implemented with Windows detached process, which
disables handle inheritance.

Fix 2/3 for issue421

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -7,7 +7,7 @@
 
 from node import hex, nullid, nullrev, short
 from i18n import _
-import os, sys, errno, re, glob
+import os, sys, errno, re, glob, tempfile, lock
 import mdiff, bdiff, util, templater, patch, error, encoding, templatekw
 import match as _match
 
@@ -567,22 +567,35 @@
     '''Run a command as a service.'''
 
     if opts['daemon'] and not opts['daemon_pipefds']:
-        rfd, wfd = os.pipe()
-        if not runargs:
-            runargs = sys.argv[:]
-        runargs.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
-        # Don't pass --cwd to the child process, because we've already
-        # changed directory.
-        for i in xrange(1,len(runargs)):
-            if runargs[i].startswith('--cwd='):
-                del runargs[i]
-                break
-            elif runargs[i].startswith('--cwd'):
-                del runargs[i:i+2]
-                break
-        pid = util.spawndetached(runargs)
-        os.close(wfd)
-        os.read(rfd, 1)
+        # Fake an already locked lock   
+        lockfd, lockpath = tempfile.mkstemp()
+        os.close(lockfd)
+        os.unlink(lockpath)    
+        util.makelock(str(os.getpid()+1), lockpath)
+        
+        try:
+            if not runargs:
+                runargs = sys.argv[:]
+            runargs.append('--daemon-pipefds=%s' % lockpath)
+            # Don't pass --cwd to the child process, because we've already
+            # changed directory.
+            for i in xrange(1,len(runargs)):
+                if runargs[i].startswith('--cwd='):
+                    del runargs[i]
+                    break
+                elif runargs[i].startswith('--cwd'):
+                    del runargs[i:i+2]
+                    break
+
+            pid = util.spawndetached(runargs)                
+            wlock = lock.lock(lockpath, sleep=0.1)
+            wlock.release()
+        finally:
+            try:
+                os.unlink(lockpath)
+            except OSError, e:
+                if e.errno != errno.ENOENT:
+                    raise
         if parentfn:
             return parentfn(pid)
         else:
@@ -598,14 +611,12 @@
         fp.close()
 
     if opts['daemon_pipefds']:
-        rfd, wfd = [int(x) for x in opts['daemon_pipefds'].split(',')]
-        os.close(rfd)
+        lockpath = opts['daemon_pipefds']
         try:
             os.setsid()
         except AttributeError:
             pass
-        os.write(wfd, 'y')
-        os.close(wfd)
+        os.unlink(lockpath)
         sys.stdout.flush()
         sys.stderr.flush()
 
diff --git a/mercurial/lock.py b/mercurial/lock.py
--- a/mercurial/lock.py
+++ b/mercurial/lock.py
@@ -29,13 +29,14 @@
 
     _host = None
 
-    def __init__(self, file, timeout=-1, releasefn=None, desc=None):
+    def __init__(self, file, timeout=-1, releasefn=None, desc=None,
+                 sleep=1):
         self.f = file
         self.held = 0
         self.timeout = timeout
         self.releasefn = releasefn
         self.desc = desc
-        self.lock()
+        self.lock(sleep=sleep)
 
     def __del__(self):
         if self.held:
@@ -49,7 +50,7 @@
 
         self.release()
 
-    def lock(self):
+    def lock(self, sleep=1):
         timeout = self.timeout
         while 1:
             try:
@@ -57,7 +58,7 @@
                 return 1
             except error.LockHeld, inst:
                 if timeout != 0:
-                    time.sleep(1)
+                    time.sleep(sleep)
                     if timeout > 0:
                         timeout -= 1
                     continue


More information about the Mercurial-devel mailing list