5 # |
5 # |
6 # This software may be used and distributed according to the terms of the |
6 # This software may be used and distributed according to the terms of the |
7 # GNU General Public License version 2, incorporated herein by reference. |
7 # GNU General Public License version 2, incorporated herein by reference. |
8 |
8 |
9 from mercurial.i18n import _ |
9 from mercurial.i18n import _ |
10 from mercurial import osutil, util |
10 from mercurial import cmdutil, osutil, util |
11 import common |
11 import common |
12 import errno, os, select, socket, stat, struct, sys, tempfile, time |
12 import errno, os, select, socket, stat, struct, sys, tempfile, time |
13 |
13 |
14 try: |
14 try: |
15 import linux as inotify |
15 import linux as inotify |
821 self.ui.note(_('finished setup\n')) |
821 self.ui.note(_('finished setup\n')) |
822 if os.getenv('TIME_STARTUP'): |
822 if os.getenv('TIME_STARTUP'): |
823 sys.exit(0) |
823 sys.exit(0) |
824 pollable.run() |
824 pollable.run() |
825 |
825 |
826 def start(ui, dirstate, root): |
826 def start(ui, dirstate, root, opts): |
827 def closefds(ignore): |
827 timeout = opts.get('timeout') |
828 # (from python bug #1177468) |
828 if timeout: |
829 # close all inherited file descriptors |
829 timeout = float(timeout) * 1e3 |
830 # Python 2.4.1 and later use /dev/urandom to seed the random module's RNG |
830 |
831 # a file descriptor is kept internally as os._urandomfd (created on demand |
831 class service(object): |
832 # the first time os.urandom() is called), and should not be closed |
832 def init(self): |
833 try: |
833 try: |
834 os.urandom(4) |
834 self.master = master(ui, dirstate, root, timeout) |
835 urandom_fd = getattr(os, '_urandomfd', None) |
835 except AlreadyStartedException, inst: |
836 except AttributeError: |
836 raise util.Abort(str(inst)) |
837 urandom_fd = None |
837 |
838 ignore.append(urandom_fd) |
838 def run(self): |
839 for fd in range(3, 256): |
839 try: |
840 if fd in ignore: |
840 self.master.run() |
841 continue |
841 finally: |
842 try: |
842 self.master.shutdown() |
843 os.close(fd) |
843 |
844 except OSError: |
844 runargs = None |
845 pass |
845 if 'inserve' not in sys.argv: |
846 |
846 runargs = [sys.argv[0], 'inserve', '-R', root] |
847 m = master(ui, dirstate, root) |
847 |
848 sys.stdout.flush() |
848 service = service() |
849 sys.stderr.flush() |
849 logfile = ui.config('inotify', 'log') |
850 |
850 cmdutil.service(opts, initfn=service.init, runfn=service.run, |
851 pid = os.fork() |
851 logfile=logfile, runargs=runargs) |
852 if pid: |
|
853 return pid |
|
854 |
|
855 closefds(pollable.instances.keys()) |
|
856 os.setsid() |
|
857 |
|
858 fd = os.open('/dev/null', os.O_RDONLY) |
|
859 os.dup2(fd, 0) |
|
860 if fd > 0: |
|
861 os.close(fd) |
|
862 |
|
863 fd = os.open(ui.config('inotify', 'log', '/dev/null'), |
|
864 os.O_RDWR | os.O_CREAT | os.O_TRUNC) |
|
865 os.dup2(fd, 1) |
|
866 os.dup2(fd, 2) |
|
867 if fd > 2: |
|
868 os.close(fd) |
|
869 |
|
870 try: |
|
871 m.run() |
|
872 finally: |
|
873 m.shutdown() |
|
874 os._exit(0) |
|