mercurial/commandserver.py
author Augie Fackler <augie@google.com>
Sun, 06 Oct 2019 09:45:02 -0400
changeset 43076 2372284d9457
parent 41284 b0e3f2d7c143
child 43077 687b865b95ad
permissions -rw-r--r--
formatting: blacken the codebase This is using my patch to black (https://github.com/psf/black/pull/826) so we don't un-wrap collection literals. Done with: hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S # skip-blame mass-reformatting only # no-check-commit reformats foo_bar functions Differential Revision: https://phab.mercurial-scm.org/D6971
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
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
    21
36940
b0ffcb540357 commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents: 36835
diff changeset
    22
    selectors.BaseSelector
b0ffcb540357 commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents: 36835
diff changeset
    23
except ImportError:
b0ffcb540357 commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents: 36835
diff changeset
    24
    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
    25
27351
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    26
from .i18n import _
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    27
from . import (
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    28
    encoding,
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    29
    error,
40824
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
    30
    loggingutil,
40589
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    31
    pycompat,
40999
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
    32
    repocache,
27351
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    33
    util,
40824
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
    34
    vfs as vfsmod,
27351
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
    35
)
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36940
diff changeset
    36
from .utils import (
40589
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    37
    cborutil,
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36940
diff changeset
    38
    procutil,
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36940
diff changeset
    39
)
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    40
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
    41
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    42
class channeledoutput(object):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    43
    """
22561
1120b1e2f975 cmdserver: correct doc of channeledoutput
Yuya Nishihara <yuya@tcha.org>
parents: 21195
diff changeset
    44
    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
    45
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    46
    data length (unsigned int),
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    47
    data
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    48
    """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
    49
22563
8cc5e673cac0 cmdserver: drop useless in_ attribute from channeledoutput
Yuya Nishihara <yuya@tcha.org>
parents: 22562
diff changeset
    50
    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
    51
        self.out = out
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    52
        self.channel = channel
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    53
27415
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
    54
    @property
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
    55
    def name(self):
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
    56
        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
    57
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    58
    def write(self, data):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    59
        if not data:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    60
            return
30263
7f2313450e86 cmdserver: write channel header and payload by a single write() call
Yuya Nishihara <yuya@tcha.org>
parents: 29609
diff changeset
    61
        # 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
    62
        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
    63
        self.out.flush()
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    64
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
    65
    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
    66
        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
    67
            raise AttributeError(attr)
22563
8cc5e673cac0 cmdserver: drop useless in_ attribute from channeledoutput
Yuya Nishihara <yuya@tcha.org>
parents: 22562
diff changeset
    68
        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
    69
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
    70
40589
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    71
class channeledmessage(object):
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    72
    """
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    73
    Write encoded message and metadata to out in the following format:
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    74
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    75
    data length (unsigned int),
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    76
    encoded message and metadata, as a flat key-value dict.
40590
83dd8c63a0c6 ui: extract helpers to write message with type or label
Yuya Nishihara <yuya@tcha.org>
parents: 40589
diff changeset
    77
83dd8c63a0c6 ui: extract helpers to write message with type or label
Yuya Nishihara <yuya@tcha.org>
parents: 40589
diff changeset
    78
    Each message should have 'type' attribute. Messages of unknown type
83dd8c63a0c6 ui: extract helpers to write message with type or label
Yuya Nishihara <yuya@tcha.org>
parents: 40589
diff changeset
    79
    should be ignored.
40589
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    80
    """
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    81
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    82
    # teach ui that write() can take **opts
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    83
    structured = True
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    84
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    85
    def __init__(self, out, channel, encodename, encodefn):
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    86
        self._cout = channeledoutput(out, channel)
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    87
        self.encoding = encodename
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    88
        self._encodefn = encodefn
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    89
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    90
    def write(self, data, **opts):
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    91
        opts = pycompat.byteskwargs(opts)
40594
234c2d8c9e48 commandserver: send raw progress information to message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40590
diff changeset
    92
        if data is not None:
234c2d8c9e48 commandserver: send raw progress information to message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40590
diff changeset
    93
            opts[b'data'] = data
40589
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    94
        self._cout.write(self._encodefn(opts))
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    95
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    96
    def __getattr__(self, attr):
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    97
        return getattr(self._cout, attr)
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
    98
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
    99
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   100
class channeledinput(object):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   101
    """
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   102
    Read data from in_.
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   103
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   104
    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
   105
    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
   106
    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
   107
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   108
    The client replies with:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   109
    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
   110
    data
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
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   113
    maxchunksize = 4 * 1024
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   114
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   115
    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
   116
        self.in_ = in_
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   117
        self.out = out
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   118
        self.channel = channel
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   119
27415
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
   120
    @property
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
   121
    def name(self):
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
   122
        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
   123
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   124
    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
   125
        if size < 0:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   126
            # 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
   127
            # 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
   128
            size = self.maxchunksize
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   129
            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
   130
            buf = s
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   131
            while s:
14728
350dcd481410 cmdserver: fix read-loop string concatenation
Idan Kamara <idankk86@gmail.com>
parents: 14719
diff changeset
   132
                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
   133
                buf += s
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   134
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   135
            return buf
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   136
        else:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   137
            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
   138
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   139
    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
   140
        if not size:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   141
            return ''
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   142
        assert size > 0
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   143
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   144
        # 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
   145
        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
   146
        self.out.flush()
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   147
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   148
        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
   149
        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
   150
        if not length:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   151
            return ''
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   152
        else:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   153
            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
   154
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   155
    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
   156
        if size < 0:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   157
            size = self.maxchunksize
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   158
            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
   159
            buf = s
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   160
            # 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
   161
            # 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
   162
            while s and s[-1] != '\n':
14728
350dcd481410 cmdserver: fix read-loop string concatenation
Idan Kamara <idankk86@gmail.com>
parents: 14719
diff changeset
   163
                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
   164
                buf += s
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   165
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   166
            return buf
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   167
        else:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   168
            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
   169
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   170
    def __iter__(self):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   171
        return self
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   172
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   173
    def next(self):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   174
        l = self.readline()
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   175
        if not l:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   176
            raise StopIteration
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   177
        return l
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   178
40358
afbfcc4e3473 py3: alias next to __next__ in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents: 40357
diff changeset
   179
    __next__ = next
afbfcc4e3473 py3: alias next to __next__ in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents: 40357
diff changeset
   180
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   181
    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
   182
        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
   183
            raise AttributeError(attr)
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   184
        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
   185
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   186
40589
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   187
_messageencoders = {
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   188
    b'cbor': lambda v: b''.join(cborutil.streamencode(v)),
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   189
}
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   190
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   191
40589
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   192
def _selectmessageencoder(ui):
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   193
    # experimental config: cmdserver.message-encodings
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   194
    encnames = ui.configlist(b'cmdserver', b'message-encodings')
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   195
    for n in encnames:
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   196
        f = _messageencoders.get(n)
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   197
        if f:
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   198
            return n, f
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   199
    raise error.Abort(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   200
        b'no supported message encodings: %s' % b' '.join(encnames)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   201
    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   202
40589
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   203
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   204
class server(object):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   205
    """
22990
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   206
    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
   207
    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
   208
    """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   209
40875
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40828
diff changeset
   210
    def __init__(self, ui, repo, fin, fout, prereposetups=None):
39818
24e493ec2229 py3: rename pycompat.getcwd() to encoding.getcwd() (API)
Matt Harbison <matt_harbison@yahoo.com>
parents: 38768
diff changeset
   211
        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
   212
20650
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   213
        if repo:
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   214
            # 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
   215
            # end up with its local configuration
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   216
            self.ui = repo.baseui
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   217
            self.repo = repo
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   218
            self.repoui = repo.ui
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   219
        else:
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   220
            self.ui = ui
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   221
            self.repo = self.repoui = None
40875
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40828
diff changeset
   222
        self._prereposetups = prereposetups
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   223
40825
eaabcb689747 commandserver: switch logging facility to ui.log() interface
Yuya Nishihara <yuya@tcha.org>
parents: 40824
diff changeset
   224
        self.cdebug = channeledoutput(fout, 'd')
22990
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   225
        self.cerr = channeledoutput(fout, 'e')
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   226
        self.cout = channeledoutput(fout, 'o')
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   227
        self.cin = channeledinput(fin, fout, 'I')
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   228
        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
   229
40824
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   230
        if self.ui.config(b'cmdserver', b'log') == b'-':
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   231
            # switch log stream of server's ui to the 'd' (debug) channel
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   232
            # (don't touch repo.ui as its lifetime is longer than the server)
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   233
            self.ui = self.ui.copy()
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   234
            setuplogging(self.ui, repo=None, fp=self.cdebug)
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   235
40589
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   236
        # TODO: add this to help/config.txt when stabilized
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   237
        # ``channel``
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   238
        #   Use separate channel for structured output. (Command-server only)
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   239
        self.cmsg = None
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   240
        if ui.config(b'ui', b'message-output') == b'channel':
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   241
            encname, encfn = _selectmessageencoder(ui)
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   242
            self.cmsg = channeledmessage(fout, b'm', encname, encfn)
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   243
22990
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
   244
        self.client = fin
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   245
29512
538d0003c9e0 commandserver: promote .cleanup() hook from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29511
diff changeset
   246
    def cleanup(self):
538d0003c9e0 commandserver: promote .cleanup() hook from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29511
diff changeset
   247
        """release and restore resources taken during server session"""
538d0003c9e0 commandserver: promote .cleanup() hook from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29511
diff changeset
   248
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   249
    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
   250
        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
   251
            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
   252
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   253
        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
   254
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   255
        # 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
   256
        if not data:
16687
e34106fa0dc3 cleanup: "raise SomeException()" -> "raise SomeException"
Brodie Rao <brodie@sf.io>
parents: 16683
diff changeset
   257
            raise EOFError
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   258
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   259
        return data
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   260
28156
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   261
    def _readstr(self):
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   262
        """read a string from the channel
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   263
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   264
        format:
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   265
        data length (uint32), data
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   266
        """
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   267
        length = struct.unpack('>I', self._read(4))[0]
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   268
        if not length:
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   269
            return ''
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   270
        return self._read(length)
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   271
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   272
    def _readlist(self):
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   273
        """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
   274
        s = self._readstr()
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   275
        if s:
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   276
            return s.split('\0')
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   277
        else:
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   278
            return []
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
   279
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   280
    def runcommand(self):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   281
        """ 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
   282
        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
   283
        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
   284
28157
e7c9b59dbbcf commandserver: use _readlist
Jun Wu <quark@fb.com>
parents: 28156
diff changeset
   285
        args = self._readlist()
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   286
14750
f5f97a0f983f cmdserver: copy repo.ui before running commands
Idan Kamara <idankk86@gmail.com>
parents: 14728
diff changeset
   287
        # 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
   288
        # persist between requests
14751
712954a67be3 cmdserver: assign repo.baseui before running commands
Idan Kamara <idankk86@gmail.com>
parents: 14750
diff changeset
   289
        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
   290
        uis = [copiedui]
20650
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   291
        if self.repo:
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   292
            self.repo.baseui = copiedui
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   293
            # 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
   294
            repoui = self.repoui.__class__(self.repoui)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   295
            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
   296
            uis.append(repoui)
20650
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
   297
            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
   298
            self.repo.invalidateall()
14751
712954a67be3 cmdserver: assign repo.baseui before running commands
Idan Kamara <idankk86@gmail.com>
parents: 14750
diff changeset
   299
21195
9336bc7dca8e cmdserver: forcibly use L channel to read password input (issue3161)
Yuya Nishihara <yuya@tcha.org>
parents: 20650
diff changeset
   300
        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
   301
            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
   302
            # 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
   303
            # 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
   304
            # 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
   305
            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
   306
                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
   307
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   308
        req = dispatch.request(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   309
            args[:],
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   310
            copiedui,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   311
            self.repo,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   312
            self.cin,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   313
            self.cout,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   314
            self.cerr,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   315
            self.cmsg,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   316
            prereposetups=self._prereposetups,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   317
        )
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   318
35652
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35461
diff changeset
   319
        try:
37995
6f9ac3cb0987 dispatch: unify handling of None returned by a command function
Yuya Nishihara <yuya@tcha.org>
parents: 37124
diff changeset
   320
            ret = dispatch.dispatch(req) & 255
35652
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35461
diff changeset
   321
            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
   322
        finally:
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35461
diff changeset
   323
            # restore old cwd
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35461
diff changeset
   324
            if '--cwd' in args:
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35461
diff changeset
   325
                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
   326
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   327
    def getencoding(self):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   328
        """ 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
   329
        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
   330
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   331
    def serveone(self):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   332
        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
   333
        if cmd:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   334
            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
   335
            if handler:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   336
                handler(self)
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   337
            else:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   338
                # 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
   339
                # 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
   340
                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
   341
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   342
        return cmd != ''
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   343
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   344
    capabilities = {'runcommand': runcommand, 'getencoding': getencoding}
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   345
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   346
    def serve(self):
18359
4b09e6f7d7de commandserver: report capabilities sorted
Mads Kiilerich <mads@kiilerich.com>
parents: 18174
diff changeset
   347
        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
   348
        hellomsg += '\n'
c19de7f32961 cmdserver: write the hello message as one chunk on the 'o' channel
Idan Kamara <idankk86@gmail.com>
parents: 14707
diff changeset
   349
        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
   350
        hellomsg += '\n'
40589
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   351
        if self.cmsg:
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40588
diff changeset
   352
            hellomsg += 'message-encoding: %s\n' % self.cmsg.encoding
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37119
diff changeset
   353
        hellomsg += 'pid: %d' % procutil.getpid()
29580
ee8186457516 commandserver: send pgid in hello message
Jun Wu <quark@fb.com>
parents: 29548
diff changeset
   354
        if util.safehasattr(os, 'getpgid'):
ee8186457516 commandserver: send pgid in hello message
Jun Wu <quark@fb.com>
parents: 29548
diff changeset
   355
            hellomsg += '\n'
ee8186457516 commandserver: send pgid in hello message
Jun Wu <quark@fb.com>
parents: 29548
diff changeset
   356
            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
   357
c19de7f32961 cmdserver: write the hello message as one chunk on the 'o' channel
Idan Kamara <idankk86@gmail.com>
parents: 14707
diff changeset
   358
        # 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
   359
        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
   360
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   361
        try:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   362
            while self.serveone():
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   363
                pass
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   364
        except EOFError:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   365
            # 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
   366
            # its request
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   367
            return 1
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   368
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
   369
        return 0
22988
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   370
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   371
40824
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   372
def setuplogging(ui, repo=None, fp=None):
40823
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40819
diff changeset
   373
    """Set up server logging facility
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40819
diff changeset
   374
40824
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   375
    If cmdserver.log is '-', log messages will be sent to the given fp.
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   376
    It should be the 'd' channel while a client is connected, and otherwise
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   377
    is the stderr of the server process.
40823
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40819
diff changeset
   378
    """
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40819
diff changeset
   379
    # developer config: cmdserver.log
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40819
diff changeset
   380
    logpath = ui.config(b'cmdserver', b'log')
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40819
diff changeset
   381
    if not logpath:
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40819
diff changeset
   382
        return
40827
d23fd01cc115 commandserver: add config knob for various logging options
Yuya Nishihara <yuya@tcha.org>
parents: 40826
diff changeset
   383
    # developer config: cmdserver.track-log
d23fd01cc115 commandserver: add config knob for various logging options
Yuya Nishihara <yuya@tcha.org>
parents: 40826
diff changeset
   384
    tracked = set(ui.configlist(b'cmdserver', b'track-log'))
40823
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40819
diff changeset
   385
40824
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   386
    if logpath == b'-' and fp:
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   387
        logger = loggingutil.fileobjectlogger(fp, tracked)
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   388
    elif logpath == b'-':
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   389
        logger = loggingutil.fileobjectlogger(ui.ferr, tracked)
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   390
    else:
40826
1617aa916d88 commandserver: expand log path for convenience
Yuya Nishihara <yuya@tcha.org>
parents: 40825
diff changeset
   391
        logpath = os.path.abspath(util.expandpath(logpath))
40827
d23fd01cc115 commandserver: add config knob for various logging options
Yuya Nishihara <yuya@tcha.org>
parents: 40826
diff changeset
   392
        # developer config: cmdserver.max-log-files
d23fd01cc115 commandserver: add config knob for various logging options
Yuya Nishihara <yuya@tcha.org>
parents: 40826
diff changeset
   393
        maxfiles = ui.configint(b'cmdserver', b'max-log-files')
d23fd01cc115 commandserver: add config knob for various logging options
Yuya Nishihara <yuya@tcha.org>
parents: 40826
diff changeset
   394
        # developer config: cmdserver.max-log-size
d23fd01cc115 commandserver: add config knob for various logging options
Yuya Nishihara <yuya@tcha.org>
parents: 40826
diff changeset
   395
        maxsize = ui.configbytes(b'cmdserver', b'max-log-size')
40824
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   396
        vfs = vfsmod.vfs(os.path.dirname(logpath))
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   397
        logger = loggingutil.filelogger(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   398
            vfs,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   399
            os.path.basename(logpath),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   400
            tracked,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   401
            maxfiles=maxfiles,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   402
            maxsize=maxsize,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   403
        )
40824
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   404
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   405
    targetuis = {ui}
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   406
    if repo:
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   407
        targetuis.add(repo.baseui)
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   408
        targetuis.add(repo.ui)
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   409
    for u in targetuis:
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   410
        u.setlogger(b'cmdserver', logger)
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40823
diff changeset
   411
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   412
22988
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   413
class pipeservice(object):
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   414
    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
   415
        self.ui = ui
bc374458688b cmdserver: postpone creation of pipe server until run()
Yuya Nishihara <yuya@tcha.org>
parents: 23322
diff changeset
   416
        self.repo = repo
22988
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   417
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   418
    def init(self):
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   419
        pass
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   420
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
   421
    def run(self):
23323
bc374458688b cmdserver: postpone creation of pipe server until run()
Yuya Nishihara <yuya@tcha.org>
parents: 23322
diff changeset
   422
        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
   423
        # 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
   424
        # hooks will never cause corruption of channel protocol.
41284
b0e3f2d7c143 ui: move protectedstdio() context manager from procutil
Yuya Nishihara <yuya@tcha.org>
parents: 40999
diff changeset
   425
        with ui.protectedfinout() as (fin, fout):
40588
9683dfb6f13a commandserver: fix reference before assignment error in pipeservice cleanup
Yuya Nishihara <yuya@tcha.org>
parents: 40361
diff changeset
   426
            sv = server(ui, self.repo, fin, fout)
37124
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   427
            try:
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   428
                return sv.serve()
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   429
            finally:
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   430
                sv.cleanup()
22989
dc8803ce3dfe cmdserver: switch service objects by mode
Yuya Nishihara <yuya@tcha.org>
parents: 22988
diff changeset
   431
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   432
29586
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
   433
def _initworkerprocess():
29609
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   434
    # 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
   435
    # 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
   436
    #    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
   437
    #    remains in a same session)
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   438
    #    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
   439
    #    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
   440
    #    cause trouble for things like ncurses.
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   441
    # 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
   442
    #    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
   443
    #    processes like ssh will be killed properly, without affecting
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
   444
    #    unrelated processes.
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   445
    os.setpgid(0, 0)
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   446
    # 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
   447
    # same state inherited from parent.
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   448
    random.seed()
29542
6011ad3b0a42 commandserver: manually create file objects from socket
Yuya Nishihara <yuya@tcha.org>
parents: 29532
diff changeset
   449
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   450
40875
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40828
diff changeset
   451
def _serverequest(ui, repo, conn, createcmdserver, prereposetups):
40359
558114fa7bc1 py3: system-stringify file mode in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents: 40358
diff changeset
   452
    fin = conn.makefile(r'rb')
558114fa7bc1 py3: system-stringify file mode in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents: 40358
diff changeset
   453
    fout = conn.makefile(r'wb')
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   454
    sv = None
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   455
    try:
40875
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40828
diff changeset
   456
        sv = createcmdserver(repo, conn, fin, fout, prereposetups)
22994
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
   457
        try:
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   458
            sv.serve()
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   459
        # 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
   460
        # known exceptions are caught by dispatch.
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   461
        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
   462
            ui.error(_('abort: %s\n') % inst)
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   463
        except IOError as inst:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   464
            if inst.errno != errno.EPIPE:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   465
                raise
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   466
        except KeyboardInterrupt:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   467
            pass
29513
e5b4d79a9140 commandserver: backport handling of forking server from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29512
diff changeset
   468
        finally:
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   469
            sv.cleanup()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   470
    except:  # re-raises
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   471
        # 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
   472
        # 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
   473
        if sv:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   474
            cerr = sv.cerr
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   475
        else:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   476
            cerr = channeledoutput(fout, 'e')
40361
b7de186efd82 py3: don't use traceback.print_exc() in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents: 40359
diff changeset
   477
        cerr.write(encoding.strtolocal(traceback.format_exc()))
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   478
        raise
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   479
    finally:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   480
        fin.close()
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   481
        try:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   482
            fout.close()  # implicit flush() may cause another EPIPE
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   483
        except IOError as inst:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   484
            if inst.errno != errno.EPIPE:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
   485
                raise
22994
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
   486
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   487
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   488
class unixservicehandler(object):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   489
    """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
   490
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   491
    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
   492
    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
   493
    """
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   494
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   495
    pollinterval = None
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   496
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   497
    def __init__(self, ui):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   498
        self.ui = ui
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   499
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   500
    def bindsocket(self, sock, address):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   501
        util.bindunixsocket(sock, address)
32236
c8b9943c07eb commandserver: move "listen" responsibility from service to handler
Jun Wu <quark@fb.com>
parents: 30924
diff changeset
   502
        sock.listen(socket.SOMAXCONN)
32237
1ada3d18e7fb commandserver: move printbanner logic to bindsocket
Jun Wu <quark@fb.com>
parents: 32236
diff changeset
   503
        self.ui.status(_('listening at %s\n') % address)
1ada3d18e7fb commandserver: move printbanner logic to bindsocket
Jun Wu <quark@fb.com>
parents: 32236
diff changeset
   504
        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
   505
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   506
    def unlinksocket(self, address):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   507
        os.unlink(address)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   508
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   509
    def shouldexit(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   510
        """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
   511
        return False
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 newconnection(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   514
        """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
   515
40875
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40828
diff changeset
   516
    def createcmdserver(self, repo, conn, fin, fout, prereposetups):
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   517
        """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
   518
        serves for the current connection"""
40875
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40828
diff changeset
   519
        return server(self.ui, repo, fin, fout, prereposetups)
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   520
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   521
29548
9da1adc18639 commandserver: drop old unixservice implementation
Yuya Nishihara <yuya@tcha.org>
parents: 29544
diff changeset
   522
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
   523
    """
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
   524
    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
   525
    """
29548
9da1adc18639 commandserver: drop old unixservice implementation
Yuya Nishihara <yuya@tcha.org>
parents: 29544
diff changeset
   526
9da1adc18639 commandserver: drop old unixservice implementation
Yuya Nishihara <yuya@tcha.org>
parents: 29544
diff changeset
   527
    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
   528
        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
   529
        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
   530
        self.address = opts['address']
29548
9da1adc18639 commandserver: drop old unixservice implementation
Yuya Nishihara <yuya@tcha.org>
parents: 29544
diff changeset
   531
        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
   532
            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
   533
        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
   534
            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
   535
        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
   536
        self._sock = None
40998
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   537
        self._mainipc = None
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   538
        self._workeripc = None
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   539
        self._oldsigchldhandler = None
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   540
        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
   541
        self._socketunlinked = None
40999
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   542
        # experimental config: cmdserver.max-repo-cache
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   543
        maxlen = ui.configint(b'cmdserver', b'max-repo-cache')
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   544
        if maxlen < 0:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   545
            raise error.Abort(_('negative max-repo-cache size not allowed'))
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   546
        self._repoloader = repocache.repoloader(ui, maxlen)
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   547
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   548
    def init(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   549
        self._sock = socket.socket(socket.AF_UNIX)
40998
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   550
        # IPC channel from many workers to one main process; this is actually
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   551
        # a uni-directional pipe, but is backed by a DGRAM socket so each
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   552
        # message can be easily separated.
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   553
        o = socket.socketpair(socket.AF_UNIX, socket.SOCK_DGRAM)
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   554
        self._mainipc, self._workeripc = o
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   555
        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
   556
        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
   557
            procutil.unblocksignal(signal.SIGCHLD)
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   558
        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
   559
        self._oldsigchldhandler = o
30887
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   560
        self._socketunlinked = False
40999
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   561
        self._repoloader.start()
30887
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   562
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   563
    def _unlinksocket(self):
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   564
        if not self._socketunlinked:
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   565
            self._servicehandler.unlinksocket(self.address)
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   566
            self._socketunlinked = True
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   567
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   568
    def _cleanup(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   569
        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
   570
        self._sock.close()
40998
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   571
        self._mainipc.close()
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   572
        self._workeripc.close()
30887
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30519
diff changeset
   573
        self._unlinksocket()
40999
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   574
        self._repoloader.stop()
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   575
        # 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
   576
        self._reapworkers(0)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   577
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   578
    def run(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   579
        try:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   580
            self._mainloop()
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   581
        finally:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   582
            self._cleanup()
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   583
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   584
    def _mainloop(self):
30891
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   585
        exiting = False
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   586
        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
   587
        selector = selectors.DefaultSelector()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   588
        selector.register(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   589
            self._sock, selectors.EVENT_READ, self._acceptnewconnection
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   590
        )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   591
        selector.register(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   592
            self._mainipc, selectors.EVENT_READ, self._handlemainipc
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   593
        )
30891
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   594
        while True:
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   595
            if not exiting and h.shouldexit():
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   596
                # 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
   597
                # we stop queuing new requests.
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   598
                # 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
   599
                # accept()-ed), handle them before exit. otherwise, clients
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   600
                # waiting for recv() will receive ECONNRESET.
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   601
                self._unlinksocket()
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30887
diff changeset
   602
                exiting = True
40788
41f0529b5112 commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents: 40361
diff changeset
   603
            try:
40878
2525faf4ecdb commandserver: loop over selector events
Yuya Nishihara <yuya@tcha.org>
parents: 40877
diff changeset
   604
                events = selector.select(timeout=h.pollinterval)
40788
41f0529b5112 commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents: 40361
diff changeset
   605
            except OSError as inst:
41f0529b5112 commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents: 40361
diff changeset
   606
                # selectors2 raises ETIMEDOUT if timeout exceeded while
41f0529b5112 commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents: 40361
diff changeset
   607
                # handling signal interrupt. That's probably wrong, but
41f0529b5112 commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents: 40361
diff changeset
   608
                # we can easily get around it.
41f0529b5112 commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents: 40361
diff changeset
   609
                if inst.errno != errno.ETIMEDOUT:
41f0529b5112 commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents: 40361
diff changeset
   610
                    raise
40878
2525faf4ecdb commandserver: loop over selector events
Yuya Nishihara <yuya@tcha.org>
parents: 40877
diff changeset
   611
                events = []
2525faf4ecdb commandserver: loop over selector events
Yuya Nishihara <yuya@tcha.org>
parents: 40877
diff changeset
   612
            if not events:
33543
3ef3bf704e47 commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents: 33506
diff changeset
   613
                # 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
   614
                if exiting:
3ef3bf704e47 commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents: 33506
diff changeset
   615
                    break
3ef3bf704e47 commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents: 33506
diff changeset
   616
                continue
40878
2525faf4ecdb commandserver: loop over selector events
Yuya Nishihara <yuya@tcha.org>
parents: 40877
diff changeset
   617
            for key, _mask in events:
2525faf4ecdb commandserver: loop over selector events
Yuya Nishihara <yuya@tcha.org>
parents: 40877
diff changeset
   618
                key.data(key.fileobj, selector)
40876
dc9901558e3c commandserver: extract handler of new socket connection
Yuya Nishihara <yuya@tcha.org>
parents: 40875
diff changeset
   619
        selector.close()
dc9901558e3c commandserver: extract handler of new socket connection
Yuya Nishihara <yuya@tcha.org>
parents: 40875
diff changeset
   620
dc9901558e3c commandserver: extract handler of new socket connection
Yuya Nishihara <yuya@tcha.org>
parents: 40875
diff changeset
   621
    def _acceptnewconnection(self, sock, selector):
dc9901558e3c commandserver: extract handler of new socket connection
Yuya Nishihara <yuya@tcha.org>
parents: 40875
diff changeset
   622
        h = self._servicehandler
40877
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   623
        try:
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   624
            conn, _addr = sock.accept()
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   625
        except socket.error as inst:
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   626
            if inst.args[0] == errno.EINTR:
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   627
                return
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   628
            raise
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   629
40999
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   630
        # Future improvement: On Python 3.7, maybe gc.freeze() can be used
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   631
        # to prevent COW memory from being touched by GC.
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   632
        # https://instagram-engineering.com/
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   633
        #   copy-on-write-friendly-python-garbage-collection-ad6ed5233ddf
40877
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   634
        pid = os.fork()
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   635
        if pid:
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   636
            try:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   637
                self.ui.log(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   638
                    b'cmdserver', b'forked worker process (pid=%d)\n', pid
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   639
                )
40877
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   640
                self._workerpids.add(pid)
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   641
                h.newconnection()
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   642
            finally:
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   643
                conn.close()  # release handle in parent process
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   644
        else:
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   645
            try:
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   646
                selector.close()
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   647
                sock.close()
40998
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   648
                self._mainipc.close()
40877
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   649
                self._runworker(conn)
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   650
                conn.close()
40998
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   651
                self._workeripc.close()
40877
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   652
                os._exit(0)
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   653
            except:  # never return, hence no re-raises
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   654
                try:
40877
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   655
                    self.ui.traceback(force=True)
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   656
                finally:
40877
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40876
diff changeset
   657
                    os._exit(255)
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   658
40998
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   659
    def _handlemainipc(self, sock, selector):
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   660
        """Process messages sent from a worker"""
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   661
        try:
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   662
            path = sock.recv(32768)  # large enough to receive path
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   663
        except socket.error as inst:
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   664
            if inst.args[0] == errno.EINTR:
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   665
                return
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   666
            raise
40999
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   667
        self._repoloader.load(path)
40998
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   668
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   669
    def _sigchldhandler(self, signal, frame):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   670
        self._reapworkers(os.WNOHANG)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   671
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   672
    def _reapworkers(self, options):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   673
        while self._workerpids:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   674
            try:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   675
                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
   676
            except OSError as inst:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   677
                if inst.errno == errno.EINTR:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   678
                    continue
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   679
                if inst.errno != errno.ECHILD:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   680
                    raise
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   681
                # 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
   682
                self._workerpids.clear()
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   683
                return
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   684
            if pid == 0:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   685
                # no waitable child processes
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   686
                return
40828
25e9089c7686 commandserver: turn server debug messages into logs
Yuya Nishihara <yuya@tcha.org>
parents: 40827
diff changeset
   687
            self.ui.log(b'cmdserver', b'worker process exited (pid=%d)\n', pid)
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   688
            self._workerpids.discard(pid)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   689
29587
536eec443b4a commandserver: rename _serveworker() to _runworker()
Yuya Nishihara <yuya@tcha.org>
parents: 29586
diff changeset
   690
    def _runworker(self, conn):
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   691
        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
   692
        _initworkerprocess()
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   693
        h = self._servicehandler
29586
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
   694
        try:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   695
            _serverequest(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   696
                self.ui,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   697
                self.repo,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   698
                conn,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   699
                h.createcmdserver,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   700
                prereposetups=[self._reposetup],
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   701
            )
29586
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
   702
        finally:
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
   703
            gc.collect()  # trigger __del__ since worker process uses os._exit
40998
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   704
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   705
    def _reposetup(self, ui, repo):
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   706
        if not repo.local():
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   707
            return
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   708
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   709
        class unixcmdserverrepo(repo.__class__):
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   710
            def close(self):
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   711
                super(unixcmdserverrepo, self).close()
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   712
                try:
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   713
                    self._cmdserveripc.send(self.root)
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   714
                except socket.error:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   715
                    self.ui.log(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   716
                        b'cmdserver', b'failed to send repo root to master\n'
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
   717
                    )
40998
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   718
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   719
        repo.__class__ = unixcmdserverrepo
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40878
diff changeset
   720
        repo._cmdserveripc = self._workeripc
40999
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   721
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   722
        cachedrepo = self._repoloader.get(repo.root)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   723
        if cachedrepo is None:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   724
            return
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   725
        repo.ui.log(b'repocache', b'repo from cache: %s\n', repo.root)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 40998
diff changeset
   726
        repocache.copycache(cachedrepo, repo)