mercurial/server.py
changeset 37215 73a60281a861
parent 37212 f09a2eab11cf
child 37216 d2bd29dffc6c
equal deleted inserted replaced
37214:3bc609bcfe77 37215:73a60281a861
    28 
    28 
    29 def runservice(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
    29 def runservice(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
    30                runargs=None, appendpid=False):
    30                runargs=None, appendpid=False):
    31     '''Run a command as a service.'''
    31     '''Run a command as a service.'''
    32 
    32 
       
    33     postexecargs = {}
       
    34 
       
    35     if opts['daemon_postexec']:
       
    36         for inst in opts['daemon_postexec']:
       
    37             if inst.startswith('unlink:'):
       
    38                 postexecargs['unlink'] = inst[7:]
       
    39             elif inst.startswith('chdir:'):
       
    40                 postexecargs['chdir'] = inst[6:]
       
    41             elif inst != 'none':
       
    42                 raise error.Abort(_('invalid value for --daemon-postexec: %s')
       
    43                                   % inst)
       
    44 
    33     # When daemonized on Windows, redirect stdout/stderr to the lockfile (which
    45     # When daemonized on Windows, redirect stdout/stderr to the lockfile (which
    34     # gets cleaned up after the child is up and running), so that the parent can
    46     # gets cleaned up after the child is up and running), so that the parent can
    35     # read and print the error if this child dies early.  See 594dd384803c.  On
    47     # read and print the error if this child dies early.  See 594dd384803c.  On
    36     # other platforms, the child can write to the parent's stdio directly, until
    48     # other platforms, the child can write to the parent's stdio directly, until
    37     # it is redirected prior to runfn().
    49     # it is redirected prior to runfn().
    38     if pycompat.iswindows and opts['daemon_postexec']:
    50     if pycompat.iswindows and opts['daemon_postexec']:
    39         for inst in opts['daemon_postexec']:
    51         if 'unlink' in postexecargs and os.path.exists(postexecargs['unlink']):
    40             if inst.startswith('unlink:'):
    52             procutil.stdout.flush()
    41                 lockpath = inst[7:]
    53             procutil.stderr.flush()
    42                 if os.path.exists(lockpath):
    54 
    43                     procutil.stdout.flush()
    55             fd = os.open(postexecargs['unlink'],
    44                     procutil.stderr.flush()
    56                          os.O_WRONLY | os.O_APPEND | os.O_BINARY)
    45 
    57             try:
    46                     fd = os.open(lockpath,
    58                 os.dup2(fd, 1)
    47                                  os.O_WRONLY | os.O_APPEND | os.O_BINARY)
    59                 os.dup2(fd, 2)
    48                     try:
    60             finally:
    49                         os.dup2(fd, 1)
    61                 os.close(fd)
    50                         os.dup2(fd, 2)
       
    51                     finally:
       
    52                         os.close(fd)
       
    53 
    62 
    54     def writepid(pid):
    63     def writepid(pid):
    55         if opts['pid_file']:
    64         if opts['pid_file']:
    56             if appendpid:
    65             if appendpid:
    57                 mode = 'ab'
    66                 mode = 'ab'
   107         try:
   116         try:
   108             os.setsid()
   117             os.setsid()
   109         except AttributeError:
   118         except AttributeError:
   110             pass
   119             pass
   111 
   120 
   112         lockpath = None
   121         if 'chdir' in postexecargs:
   113         for inst in opts['daemon_postexec']:
   122             os.chdir(postexecargs['chdir'])
   114             if inst.startswith('unlink:'):
       
   115                 lockpath = inst[7:]
       
   116             elif inst.startswith('chdir:'):
       
   117                 os.chdir(inst[6:])
       
   118             elif inst != 'none':
       
   119                 raise error.Abort(_('invalid value for --daemon-postexec: %s')
       
   120                                   % inst)
       
   121         procutil.hidewindow()
   123         procutil.hidewindow()
   122         procutil.stdout.flush()
   124         procutil.stdout.flush()
   123         procutil.stderr.flush()
   125         procutil.stderr.flush()
   124 
   126 
   125         nullfd = os.open(os.devnull, os.O_RDWR)
   127         nullfd = os.open(os.devnull, os.O_RDWR)
   135         if logfile and logfilefd not in (0, 1, 2):
   137         if logfile and logfilefd not in (0, 1, 2):
   136             os.close(logfilefd)
   138             os.close(logfilefd)
   137 
   139 
   138         # Only unlink after redirecting stdout/stderr, so Windows doesn't
   140         # Only unlink after redirecting stdout/stderr, so Windows doesn't
   139         # complain about a sharing violation.
   141         # complain about a sharing violation.
   140         if lockpath:
   142         if 'unlink' in postexecargs:
   141             os.unlink(lockpath)
   143             os.unlink(postexecargs['unlink'])
   142 
   144 
   143     if runfn:
   145     if runfn:
   144         return runfn()
   146         return runfn()
   145 
   147 
   146 _cmdservicemap = {
   148 _cmdservicemap = {