mercurial/commandserver.py
author Yuya Nishihara <yuya@tcha.org>
Tue, 16 Oct 2018 08:20:03 +0200
changeset 40359 558114fa7bc1
parent 40358 afbfcc4e3473
child 40361 b7de186efd82
permissions -rw-r--r--
py3: system-stringify file mode in commandserver.py # skip-blame just r'' prefixes
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
     1
# commandserver.py - communicate with Mercurial's API over a pipe
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
     2
#
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
     3
#  Copyright Matt Mackall <mpm@selenic.com>
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
     4
#
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
     7
27351
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
     8
from __future__ import absolute_import
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
     9
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    10
import errno
29513
e5b4d79a9140 commandserver: backport handling of forking server from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29512
diff changeset
    11
import gc
27351
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    12
import os
29513
e5b4d79a9140 commandserver: backport handling of forking server from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29512
diff changeset
    13
import random
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
    14
import signal
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
    15
import socket
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    16
import struct
27351
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    17
import traceback
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    18
36940
b0ffcb540357 commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents: 36835
diff changeset
    19
try:
b0ffcb540357 commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents: 36835
diff changeset
    20
    import selectors
b0ffcb540357 commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents: 36835
diff changeset
    21
    selectors.BaseSelector
b0ffcb540357 commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents: 36835
diff changeset
    22
except ImportError:
b0ffcb540357 commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents: 36835
diff changeset
    23
    from .thirdparty import selectors2 as selectors
b0ffcb540357 commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents: 36835
diff changeset
    24
27351
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    25
from .i18n import _
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    26
from . import (
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    27
    encoding,
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    28
    error,
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    29
    util,
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    30
)
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36940
diff changeset
    31
from .utils import (
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36940
diff changeset
    32
    procutil,
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36940
diff changeset
    33
)
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    34
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    35
logfile = None
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    36
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    37
def log(*args):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    38
    if not logfile:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    39
        return
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    40
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    41
    for a in args:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    42
        logfile.write(str(a))
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    43
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    44
    logfile.flush()
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    45
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    46
class channeledoutput(object):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    47
    """
22561
1120b1e2f975 cmdserver: correct doc of channeledoutput
Yuya Nishihara <yuya@tcha.org>
parents: 21195
diff changeset
    48
    Write data to out in the following format:
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    49
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    50
    data length (unsigned int),
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    51
    data
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    52
    """
22563
8cc5e673cac0 cmdserver: drop useless in_ attribute from channeledoutput
Yuya Nishihara <yuya@tcha.org>
parents: 22562
diff changeset
    53
    def __init__(self, out, channel):
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    54
        self.out = out
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    55
        self.channel = channel
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    56
27415
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
    57
    @property
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
    58
    def name(self):
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
    59
        return '<%c-channel>' % self.channel
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
    60
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    61
    def write(self, data):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    62
        if not data:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    63
            return
30263
7f2313450e86 cmdserver: write channel header and payload by a single write() call
Yuya Nishihara <yuya@tcha.org>
parents: 29609
diff changeset
    64
        # single write() to guarantee the same atomicity as the underlying file
7f2313450e86 cmdserver: write channel header and payload by a single write() call
Yuya Nishihara <yuya@tcha.org>
parents: 29609
diff changeset
    65
        self.out.write(struct.pack('>cI', self.channel, len(data)) + data)
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    66
        self.out.flush()
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    67
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    68
    def __getattr__(self, attr):
40357
efbf7de09d2a py3: system-stringify list of attributes to be forwarded from commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents: 39818
diff changeset
    69
        if attr in (r'isatty', r'fileno', r'tell', r'seek'):
18174
56ef99fbd6f2 commandserver: clean up use of two-argument raise
Augie Fackler <raf@durin42.com>
parents: 17425
diff changeset
    70
            raise AttributeError(attr)
22563
8cc5e673cac0 cmdserver: drop useless in_ attribute from channeledoutput
Yuya Nishihara <yuya@tcha.org>
parents: 22562
diff changeset
    71
        return getattr(self.out, attr)
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    72
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    73
class channeledinput(object):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    74
    """
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    75
    Read data from in_.
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    76
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    77
    Requests for input are written to out in the following format:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    78
    channel identifier - 'I' for plain input, 'L' line based (1 byte)
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    79
    how many bytes to send at most (unsigned int),
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    80
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    81
    The client replies with:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    82
    data length (unsigned int), 0 meaning EOF
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    83
    data
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    84
    """
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    85
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    86
    maxchunksize = 4 * 1024
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    87
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    88
    def __init__(self, in_, out, channel):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    89
        self.in_ = in_
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    90
        self.out = out
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    91
        self.channel = channel
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    92
27415
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
    93
    @property
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
    94
    def name(self):
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
    95
        return '<%c-channel>' % self.channel
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
    96
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    97
    def read(self, size=-1):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    98
        if size < 0:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    99
            # if we need to consume all the clients input, ask for 4k chunks
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   100
            # so the pipe doesn't fill up risking a deadlock
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   101
            size = self.maxchunksize
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   102
            s = self._read(size, self.channel)
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   103
            buf = s
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   104
            while s:
14728
350dcd481410 cmdserver: fix read-loop string concatenation
Idan Kamara <idankk86@gmail.com>
parents: 14719
diff changeset
   105
                s = self._read(size, self.channel)
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   106
                buf += s
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   107
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   108
            return buf
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   109
        else:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   110
            return self._read(size, self.channel)
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   111
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   112
    def _read(self, size, channel):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   113
        if not size:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   114
            return ''
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   115
        assert size > 0
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   116
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   117
        # tell the client we need at most size bytes
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   118
        self.out.write(struct.pack('>cI', channel, size))
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   119
        self.out.flush()
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   120
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   121
        length = self.in_.read(4)
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   122
        length = struct.unpack('>I', length)[0]
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   123
        if not length:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   124
            return ''
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   125
        else:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   126
            return self.in_.read(length)
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   127
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   128
    def readline(self, size=-1):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   129
        if size < 0:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   130
            size = self.maxchunksize
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   131
            s = self._read(size, 'L')
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   132
            buf = s
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   133
            # keep asking for more until there's either no more or
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   134
            # we got a full line
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   135
            while s and s[-1] != '\n':
14728
350dcd481410 cmdserver: fix read-loop string concatenation
Idan Kamara <idankk86@gmail.com>
parents: 14719
diff changeset
   136
                s = self._read(size, 'L')
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   137
                buf += s
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   138
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   139
            return buf
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   140
        else:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   141
            return self._read(size, 'L')
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   142
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   143
    def __iter__(self):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   144
        return self
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   145
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   146
    def next(self):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   147
        l = self.readline()
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   148
        if not l:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   149
            raise StopIteration
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   150
        return l
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   151
40358
afbfcc4e3473 py3: alias next to __next__ in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents: 40357
diff changeset
   152
    __next__ = next
afbfcc4e3473 py3: alias next to __next__ in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents: 40357
diff changeset
   153
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   154
    def __getattr__(self, attr):
40357
efbf7de09d2a py3: system-stringify list of attributes to be forwarded from commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents: 39818
diff changeset
   155
        if attr in (r'isatty', r'fileno', r'tell', r'seek'):
18174
56ef99fbd6f2 commandserver: clean up use of two-argument raise
Augie Fackler <raf@durin42.com>
parents: 17425
diff changeset
   156
            raise AttributeError(attr)
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   157
        return getattr(self.in_, attr)
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   158
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   159
class server(object):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   160
    """
22990
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   161
    Listens for commands on fin, runs them and writes the output on a channel
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   162
    based stream to fout.
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   163
    """
22990
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   164
    def __init__(self, ui, repo, fin, fout):
39818
24e493ec2229 py3: rename pycompat.getcwd() to encoding.getcwd() (API)
Matt Harbison <matt_harbison@yahoo.com>
parents: 38768
diff changeset
   165
        self.cwd = encoding.getcwd()
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   166
25832
5857be01962e commandserver: mark developer-only logging option
Matt Mackall <mpm@selenic.com>
parents: 25660
diff changeset
   167
        # developer config: cmdserver.log
33499
0407a51b9d8c codemod: register core configitems using a script
Jun Wu <quark@fb.com>
parents: 32237
diff changeset
   168
        logpath = ui.config("cmdserver", "log")
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   169
        if logpath:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   170
            global logfile
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   171
            if logpath == '-':
17425
e95ec38f86b0 fix wording and not-completely-trivial spelling errors and bad docstrings
Mads Kiilerich <mads@kiilerich.com>
parents: 16687
diff changeset
   172
                # write log on a special 'd' (debug) channel
22990
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   173
                logfile = channeledoutput(fout, 'd')
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   174
            else:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   175
                logfile = open(logpath, 'a')
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   176
20650
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   177
        if repo:
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   178
            # the ui here is really the repo ui so take its baseui so we don't
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   179
            # end up with its local configuration
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   180
            self.ui = repo.baseui
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   181
            self.repo = repo
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   182
            self.repoui = repo.ui
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   183
        else:
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   184
            self.ui = ui
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   185
            self.repo = self.repoui = None
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   186
22990
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   187
        self.cerr = channeledoutput(fout, 'e')
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   188
        self.cout = channeledoutput(fout, 'o')
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   189
        self.cin = channeledinput(fin, fout, 'I')
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   190
        self.cresult = channeledoutput(fout, 'r')
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   191
22990
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   192
        self.client = fin
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   193
29512
538d0003c9e0 commandserver: promote .cleanup() hook from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29511
diff changeset
   194
    def cleanup(self):
538d0003c9e0 commandserver: promote .cleanup() hook from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29511
diff changeset
   195
        """release and restore resources taken during server session"""
538d0003c9e0 commandserver: promote .cleanup() hook from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29511
diff changeset
   196
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   197
    def _read(self, size):
14706
5fd5dd9a610a cmdserver: don't raise EOFError when trying to read 0 bytes from the client
Idan Kamara <idankk86@gmail.com>
parents: 14647
diff changeset
   198
        if not size:
5fd5dd9a610a cmdserver: don't raise EOFError when trying to read 0 bytes from the client
Idan Kamara <idankk86@gmail.com>
parents: 14647
diff changeset
   199
            return ''
5fd5dd9a610a cmdserver: don't raise EOFError when trying to read 0 bytes from the client
Idan Kamara <idankk86@gmail.com>
parents: 14647
diff changeset
   200
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   201
        data = self.client.read(size)
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   202
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   203
        # is the other end closed?
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   204
        if not data:
16687
e34106fa0dc3 cleanup: "raise SomeException()" -> "raise SomeException"
Brodie Rao <brodie@sf.io>
parents: 16683
diff changeset
   205
            raise EOFError
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   206
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   207
        return data
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   208
28156
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   209
    def _readstr(self):
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   210
        """read a string from the channel
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   211
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   212
        format:
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   213
        data length (uint32), data
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   214
        """
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   215
        length = struct.unpack('>I', self._read(4))[0]
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   216
        if not length:
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   217
            return ''
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   218
        return self._read(length)
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   219
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   220
    def _readlist(self):
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   221
        """read a list of NULL separated strings from the channel"""
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   222
        s = self._readstr()
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   223
        if s:
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   224
            return s.split('\0')
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   225
        else:
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   226
            return []
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   227
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   228
    def runcommand(self):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   229
        """ reads a list of \0 terminated arguments, executes
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   230
        and writes the return code to the result channel """
27352
9fd8f1552369 commandserver: cut import cycle by itself
Yuya Nishihara <yuya@tcha.org>
parents: 27351
diff changeset
   231
        from . import dispatch  # avoid cycle
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   232
28157
e7c9b59dbbcf commandserver: use _readlist
Jun Wu <quark@fb.com>
parents: 28156
diff changeset
   233
        args = self._readlist()
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   234
14750
f5f97a0f983f cmdserver: copy repo.ui before running commands
Idan Kamara <idankk86@gmail.com>
parents: 14728
diff changeset
   235
        # copy the uis so changes (e.g. --config or --verbose) don't
f5f97a0f983f cmdserver: copy repo.ui before running commands
Idan Kamara <idankk86@gmail.com>
parents: 14728
diff changeset
   236
        # persist between requests
14751
712954a67be3 cmdserver: assign repo.baseui before running commands
Idan Kamara <idankk86@gmail.com>
parents: 14750
diff changeset
   237
        copiedui = self.ui.copy()
21195
9336bc7dca8e cmdserver: forcibly use L channel to read password input (issue3161)
Yuya Nishihara <yuya@tcha.org>
parents: 20650
diff changeset
   238
        uis = [copiedui]
20650
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   239
        if self.repo:
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   240
            self.repo.baseui = copiedui
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   241
            # clone ui without using ui.copy because this is protected
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   242
            repoui = self.repoui.__class__(self.repoui)
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   243
            repoui.copy = copiedui.copy # redo copy protection
21195
9336bc7dca8e cmdserver: forcibly use L channel to read password input (issue3161)
Yuya Nishihara <yuya@tcha.org>
parents: 20650
diff changeset
   244
            uis.append(repoui)
20650
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   245
            self.repo.ui = self.repo.dirstate._ui = repoui
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   246
            self.repo.invalidateall()
14751
712954a67be3 cmdserver: assign repo.baseui before running commands
Idan Kamara <idankk86@gmail.com>
parents: 14750
diff changeset
   247
21195
9336bc7dca8e cmdserver: forcibly use L channel to read password input (issue3161)
Yuya Nishihara <yuya@tcha.org>
parents: 20650
diff changeset
   248
        for ui in uis:
29366
d269e7db2f55 ui: provide official way to reset internal state per command
Yuya Nishihara <yuya@tcha.org>
parents: 28511
diff changeset
   249
            ui.resetstate()
27565
e7937438e3f7 commandserver: do not set nontty flag if channel is replaced by a real file
Yuya Nishihara <yuya@tcha.org>
parents: 27415
diff changeset
   250
            # any kind of interaction must use server channels, but chg may
e7937438e3f7 commandserver: do not set nontty flag if channel is replaced by a real file
Yuya Nishihara <yuya@tcha.org>
parents: 27415
diff changeset
   251
            # replace channels by fully functional tty files. so nontty is
e7937438e3f7 commandserver: do not set nontty flag if channel is replaced by a real file
Yuya Nishihara <yuya@tcha.org>
parents: 27415
diff changeset
   252
            # enforced only if cin is a channel.
e7937438e3f7 commandserver: do not set nontty flag if channel is replaced by a real file
Yuya Nishihara <yuya@tcha.org>
parents: 27415
diff changeset
   253
            if not util.safehasattr(self.cin, 'fileno'):
e7937438e3f7 commandserver: do not set nontty flag if channel is replaced by a real file
Yuya Nishihara <yuya@tcha.org>
parents: 27415
diff changeset
   254
                ui.setconfig('ui', 'nontty', 'true', 'commandserver')
21195
9336bc7dca8e cmdserver: forcibly use L channel to read password input (issue3161)
Yuya Nishihara <yuya@tcha.org>
parents: 20650
diff changeset
   255
14864
1b872599f39f cmdserver: restore old working dir after dispatch when we have --cwd
Idan Kamara <idankk86@gmail.com>
parents: 14751
diff changeset
   256
        req = dispatch.request(args[:], copiedui, self.repo, self.cin,
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   257
                               self.cout, self.cerr)
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   258
35652
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35461
diff changeset
   259
        try:
37995
6f9ac3cb0987 dispatch: unify handling of None returned by a command function
Yuya Nishihara <yuya@tcha.org>
parents: 37124
diff changeset
   260
            ret = dispatch.dispatch(req) & 255
35652
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35461
diff changeset
   261
            self.cresult.write(struct.pack('>i', int(ret)))
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35461
diff changeset
   262
        finally:
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35461
diff changeset
   263
            # restore old cwd
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35461
diff changeset
   264
            if '--cwd' in args:
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35461
diff changeset
   265
                os.chdir(self.cwd)
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   266
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   267
    def getencoding(self):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   268
        """ writes the current encoding to the result channel """
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   269
        self.cresult.write(encoding.encoding)
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   270
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   271
    def serveone(self):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   272
        cmd = self.client.readline()[:-1]
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   273
        if cmd:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   274
            handler = self.capabilities.get(cmd)
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   275
            if handler:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   276
                handler(self)
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   277
            else:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   278
                # clients are expected to check what commands are supported by
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   279
                # looking at the servers capabilities
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25832
diff changeset
   280
                raise error.Abort(_('unknown command %s') % cmd)
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   281
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   282
        return cmd != ''
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   283
34486
a57c938e7ac8 style: never use a space before a colon or comma
Alex Gaynor <agaynor@mozilla.com>
parents: 34373
diff changeset
   284
    capabilities = {'runcommand': runcommand,
a57c938e7ac8 style: never use a space before a colon or comma
Alex Gaynor <agaynor@mozilla.com>
parents: 34373
diff changeset
   285
                    'getencoding': getencoding}
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   286
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   287
    def serve(self):
18359
4b09e6f7d7de commandserver: report capabilities sorted
Mads Kiilerich <mads@kiilerich.com>
parents: 18174
diff changeset
   288
        hellomsg = 'capabilities: ' + ' '.join(sorted(self.capabilities))
14719
c19de7f32961 cmdserver: write the hello message as one chunk on the 'o' channel
Idan Kamara <idankk86@gmail.com>
parents: 14707
diff changeset
   289
        hellomsg += '\n'
c19de7f32961 cmdserver: write the hello message as one chunk on the 'o' channel
Idan Kamara <idankk86@gmail.com>
parents: 14707
diff changeset
   290
        hellomsg += 'encoding: ' + encoding.encoding
23036
19f5273c9f3e cmdserver: include pid of server handling requests in hello message
Yuya Nishihara <yuya@tcha.org>
parents: 22994
diff changeset
   291
        hellomsg += '\n'
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37119
diff changeset
   292
        hellomsg += 'pid: %d' % procutil.getpid()
29580
ee8186457516 commandserver: send pgid in hello message
Jun Wu <quark@fb.com>
parents: 29548
diff changeset
   293
        if util.safehasattr(os, 'getpgid'):
ee8186457516 commandserver: send pgid in hello message
Jun Wu <quark@fb.com>
parents: 29548
diff changeset
   294
            hellomsg += '\n'
ee8186457516 commandserver: send pgid in hello message
Jun Wu <quark@fb.com>
parents: 29548
diff changeset
   295
            hellomsg += 'pgid: %d' % os.getpgid(0)
14719
c19de7f32961 cmdserver: write the hello message as one chunk on the 'o' channel
Idan Kamara <idankk86@gmail.com>
parents: 14707
diff changeset
   296
c19de7f32961 cmdserver: write the hello message as one chunk on the 'o' channel
Idan Kamara <idankk86@gmail.com>
parents: 14707
diff changeset
   297
        # write the hello msg in -one- chunk
c19de7f32961 cmdserver: write the hello message as one chunk on the 'o' channel
Idan Kamara <idankk86@gmail.com>
parents: 14707
diff changeset
   298
        self.cout.write(hellomsg)
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   299
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   300
        try:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   301
            while self.serveone():
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   302
                pass
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   303
        except EOFError:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   304
            # we'll get here if the client disconnected while we were reading
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   305
            # its request
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   306
            return 1
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   307
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   308
        return 0
22988
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   309
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   310
class pipeservice(object):
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   311
    def __init__(self, ui, repo, opts):
23323
bc374458688b cmdserver: postpone creation of pipe server until run()
Yuya Nishihara <yuya@tcha.org>
parents: 23322
diff changeset
   312
        self.ui = ui
bc374458688b cmdserver: postpone creation of pipe server until run()
Yuya Nishihara <yuya@tcha.org>
parents: 23322
diff changeset
   313
        self.repo = repo
22988
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   314
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   315
    def init(self):
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   316
        pass
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   317
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   318
    def run(self):
23323
bc374458688b cmdserver: postpone creation of pipe server until run()
Yuya Nishihara <yuya@tcha.org>
parents: 23322
diff changeset
   319
        ui = self.ui
23324
69f86b937035 cmdserver: protect pipe server streams against corruption caused by direct io
Yuya Nishihara <yuya@tcha.org>
parents: 23323
diff changeset
   320
        # redirect stdio to null device so that broken extensions or in-process
69f86b937035 cmdserver: protect pipe server streams against corruption caused by direct io
Yuya Nishihara <yuya@tcha.org>
parents: 23323
diff changeset
   321
        # hooks will never cause corruption of channel protocol.
37124
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   322
        with procutil.protectedstdio(ui.fin, ui.fout) as (fin, fout):
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   323
            try:
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   324
                sv = server(ui, self.repo, fin, fout)
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   325
                return sv.serve()
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   326
            finally:
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   327
                sv.cleanup()
22989
dc8803ce3dfe cmdserver: switch service objects by mode
Yuya Nishihara <yuya@tcha.org>
parents: 22988
diff changeset
   328
29586
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
   329
def _initworkerprocess():
29609
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   330
    # use a different process group from the master process, in order to:
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   331
    # 1. make the current process group no longer "orphaned" (because the
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   332
    #    parent of this process is in a different process group while
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   333
    #    remains in a same session)
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   334
    #    according to POSIX 2.2.2.52, orphaned process group will ignore
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   335
    #    terminal-generated stop signals like SIGTSTP (Ctrl+Z), which will
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   336
    #    cause trouble for things like ncurses.
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   337
    # 2. the client can use kill(-pgid, sig) to simulate terminal-generated
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   338
    #    SIGINT (Ctrl+C) and process-exit-generated SIGHUP. our child
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   339
    #    processes like ssh will be killed properly, without affecting
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   340
    #    unrelated processes.
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   341
    os.setpgid(0, 0)
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   342
    # change random state otherwise forked request handlers would have a
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   343
    # same state inherited from parent.
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   344
    random.seed()
29542
6011ad3b0a42 commandserver: manually create file objects from socket
Yuya Nishihara <yuya@tcha.org>
parents: 29532
diff changeset
   345
29586
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
   346
def _serverequest(ui, repo, conn, createcmdserver):
40359
558114fa7bc1 py3: system-stringify file mode in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents: 40358
diff changeset
   347
    fin = conn.makefile(r'rb')
558114fa7bc1 py3: system-stringify file mode in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents: 40358
diff changeset
   348
    fout = conn.makefile(r'wb')
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   349
    sv = None
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   350
    try:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   351
        sv = createcmdserver(repo, conn, fin, fout)
22994
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
   352
        try:
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   353
            sv.serve()
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   354
        # handle exceptions that may be raised by command server. most of
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   355
        # known exceptions are caught by dispatch.
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   356
        except error.Abort as inst:
38768
afc4ad706f9c dispatch: making all hg abortions be output with a specific label
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 38291
diff changeset
   357
            ui.error(_('abort: %s\n') % inst)
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   358
        except IOError as inst:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   359
            if inst.errno != errno.EPIPE:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   360
                raise
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   361
        except KeyboardInterrupt:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   362
            pass
29513
e5b4d79a9140 commandserver: backport handling of forking server from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29512
diff changeset
   363
        finally:
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   364
            sv.cleanup()
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   365
    except: # re-raises
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   366
        # also write traceback to error channel. otherwise client cannot
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   367
        # see it because it is written to server's stderr by default.
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   368
        if sv:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   369
            cerr = sv.cerr
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   370
        else:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   371
            cerr = channeledoutput(fout, 'e')
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   372
        traceback.print_exc(file=cerr)
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   373
        raise
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   374
    finally:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   375
        fin.close()
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   376
        try:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   377
            fout.close()  # implicit flush() may cause another EPIPE
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   378
        except IOError as inst:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   379
            if inst.errno != errno.EPIPE:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   380
                raise
22994
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
   381
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   382
class unixservicehandler(object):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   383
    """Set of pluggable operations for unix-mode services
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   384
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   385
    Almost all methods except for createcmdserver() are called in the main
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   386
    process. You can't pass mutable resource back from createcmdserver().
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   387
    """
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   388
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   389
    pollinterval = None
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   390
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   391
    def __init__(self, ui):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   392
        self.ui = ui
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   393
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   394
    def bindsocket(self, sock, address):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   395
        util.bindunixsocket(sock, address)
32236
c8b9943c07eb commandserver: move "listen" responsibility from service to handler
Jun Wu <quark@fb.com>
parents: 30924
diff changeset
   396
        sock.listen(socket.SOMAXCONN)
32237
1ada3d18e7fb commandserver: move printbanner logic to bindsocket
Jun Wu <quark@fb.com>
parents: 32236
diff changeset
   397
        self.ui.status(_('listening at %s\n') % address)
1ada3d18e7fb commandserver: move printbanner logic to bindsocket
Jun Wu <quark@fb.com>
parents: 32236
diff changeset
   398
        self.ui.flush()  # avoid buffering of status message
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   399
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   400
    def unlinksocket(self, address):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   401
        os.unlink(address)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   402
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   403
    def shouldexit(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   404
        """True if server should shut down; checked per pollinterval"""
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   405
        return False
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   406
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   407
    def newconnection(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   408
        """Called when main process notices new connection"""
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   409
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   410
    def createcmdserver(self, repo, conn, fin, fout):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   411
        """Create new command server instance; called in the process that
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   412
        serves for the current connection"""
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   413
        return server(self.ui, repo, fin, fout)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   414
29548
9da1adc18639 commandserver: drop old unixservice implementation
Yuya Nishihara <yuya@tcha.org>
parents: 29544
diff changeset
   415
class unixforkingservice(object):
22994
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
   416
    """
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
   417
    Listens on unix domain socket and forks server per connection
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
   418
    """
29548
9da1adc18639 commandserver: drop old unixservice implementation
Yuya Nishihara <yuya@tcha.org>
parents: 29544
diff changeset
   419
9da1adc18639 commandserver: drop old unixservice implementation
Yuya Nishihara <yuya@tcha.org>
parents: 29544
diff changeset
   420
    def __init__(self, ui, repo, opts, handler=None):
22994
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
   421
        self.ui = ui
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
   422
        self.repo = repo
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
   423
        self.address = opts['address']
29548
9da1adc18639 commandserver: drop old unixservice implementation
Yuya Nishihara <yuya@tcha.org>
parents: 29544
diff changeset
   424
        if not util.safehasattr(socket, 'AF_UNIX'):
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25832
diff changeset
   425
            raise error.Abort(_('unsupported platform'))
22994
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
   426
        if not self.address:
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25832
diff changeset
   427
            raise error.Abort(_('no socket path specified with --address'))
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   428
        self._servicehandler = handler or unixservicehandler(ui)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   429
        self._sock = None
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   430
        self._oldsigchldhandler = None
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   431
        self._workerpids = set()  # updated by signal handler; do not iterate
30887
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   432
        self._socketunlinked = None
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   433
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   434
    def init(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   435
        self._sock = socket.socket(socket.AF_UNIX)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   436
        self._servicehandler.bindsocket(self._sock, self.address)
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37119
diff changeset
   437
        if util.safehasattr(procutil, 'unblocksignal'):
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37119
diff changeset
   438
            procutil.unblocksignal(signal.SIGCHLD)
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   439
        o = signal.signal(signal.SIGCHLD, self._sigchldhandler)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   440
        self._oldsigchldhandler = o
30887
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   441
        self._socketunlinked = False
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   442
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   443
    def _unlinksocket(self):
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   444
        if not self._socketunlinked:
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   445
            self._servicehandler.unlinksocket(self.address)
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   446
            self._socketunlinked = True
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   447
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   448
    def _cleanup(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   449
        signal.signal(signal.SIGCHLD, self._oldsigchldhandler)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   450
        self._sock.close()
30887
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   451
        self._unlinksocket()
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   452
        # don't kill child processes as they have active clients, just wait
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   453
        self._reapworkers(0)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   454
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   455
    def run(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   456
        try:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   457
            self._mainloop()
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   458
        finally:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   459
            self._cleanup()
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   460
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   461
    def _mainloop(self):
30891
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   462
        exiting = False
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   463
        h = self._servicehandler
36940
b0ffcb540357 commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents: 36835
diff changeset
   464
        selector = selectors.DefaultSelector()
b0ffcb540357 commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents: 36835
diff changeset
   465
        selector.register(self._sock, selectors.EVENT_READ)
30891
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   466
        while True:
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   467
            if not exiting and h.shouldexit():
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   468
                # clients can no longer connect() to the domain socket, so
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   469
                # we stop queuing new requests.
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   470
                # for requests that are queued (connect()-ed, but haven't been
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   471
                # accept()-ed), handle them before exit. otherwise, clients
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   472
                # waiting for recv() will receive ECONNRESET.
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   473
                self._unlinksocket()
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   474
                exiting = True
33543
3ef3bf704e47 commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents: 33506
diff changeset
   475
            ready = selector.select(timeout=h.pollinterval)
3ef3bf704e47 commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents: 33506
diff changeset
   476
            if not ready:
3ef3bf704e47 commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents: 33506
diff changeset
   477
                # only exit if we completed all queued requests
3ef3bf704e47 commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents: 33506
diff changeset
   478
                if exiting:
3ef3bf704e47 commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents: 33506
diff changeset
   479
                    break
3ef3bf704e47 commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents: 33506
diff changeset
   480
                continue
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   481
            try:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   482
                conn, _addr = self._sock.accept()
33543
3ef3bf704e47 commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents: 33506
diff changeset
   483
            except socket.error as inst:
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   484
                if inst.args[0] == errno.EINTR:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   485
                    continue
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   486
                raise
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   487
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   488
            pid = os.fork()
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   489
            if pid:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   490
                try:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   491
                    self.ui.debug('forked worker process (pid=%d)\n' % pid)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   492
                    self._workerpids.add(pid)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   493
                    h.newconnection()
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   494
                finally:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   495
                    conn.close()  # release handle in parent process
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   496
            else:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   497
                try:
38291
c07424ec633c commandserver: close server's fds explicitly from a worker
Jun Wu <quark@fb.com>
parents: 37995
diff changeset
   498
                    selector.close()
c07424ec633c commandserver: close server's fds explicitly from a worker
Jun Wu <quark@fb.com>
parents: 37995
diff changeset
   499
                    self._sock.close()
29587
536eec443b4a commandserver: rename _serveworker() to _runworker()
Yuya Nishihara <yuya@tcha.org>
parents: 29586
diff changeset
   500
                    self._runworker(conn)
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   501
                    conn.close()
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   502
                    os._exit(0)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   503
                except:  # never return, hence no re-raises
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   504
                    try:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   505
                        self.ui.traceback(force=True)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   506
                    finally:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   507
                        os._exit(255)
33506
8a1a7935c047 commandserver: close selector explicitly
Jun Wu <quark@fb.com>
parents: 33503
diff changeset
   508
        selector.close()
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   509
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   510
    def _sigchldhandler(self, signal, frame):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   511
        self._reapworkers(os.WNOHANG)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   512
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   513
    def _reapworkers(self, options):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   514
        while self._workerpids:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   515
            try:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   516
                pid, _status = os.waitpid(-1, options)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   517
            except OSError as inst:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   518
                if inst.errno == errno.EINTR:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   519
                    continue
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   520
                if inst.errno != errno.ECHILD:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   521
                    raise
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   522
                # no child processes at all (reaped by other waitpid()?)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   523
                self._workerpids.clear()
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   524
                return
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   525
            if pid == 0:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   526
                # no waitable child processes
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   527
                return
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   528
            self.ui.debug('worker process exited (pid=%d)\n' % pid)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   529
            self._workerpids.discard(pid)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   530
29587
536eec443b4a commandserver: rename _serveworker() to _runworker()
Yuya Nishihara <yuya@tcha.org>
parents: 29586
diff changeset
   531
    def _runworker(self, conn):
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   532
        signal.signal(signal.SIGCHLD, self._oldsigchldhandler)
29586
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
   533
        _initworkerprocess()
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   534
        h = self._servicehandler
29586
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
   535
        try:
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
   536
            _serverequest(self.ui, self.repo, conn, h.createcmdserver)
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
   537
        finally:
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
   538
            gc.collect()  # trigger __del__ since worker process uses os._exit