annotate mercurial/commandserver.py @ 49288:311fcc5a65f6

thirdparty: remove Python 2-specific selectors2 copy The selectors module was added in Python 3.4. Because we require Python 3.6, it will always be available. Therefore the selectors2 module is not imported. I?ve verified that the selectors2-specific workaround in commandserver.py is not necessary with the selectors module from the standard library. It returns an empty list if timeout was exceeded. The pytype directive was needed to silence the following error: File "/tmp/mercurial-ci/mercurial/worker.py", line 299, in _posixworker: No attribute 'close' on int [attribute-error] In Union[_typeshed.HasFileno, int] File "/tmp/mercurial-ci/mercurial/worker.py", line 299, in _posixworker: No attribute 'close' on _typeshed.HasFileno [attribute-error] In Union[_typeshed.HasFileno, int]
author Manuel Jacob <me@manueljacob.de>
date Sat, 28 May 2022 22:08:13 +0200
parents 642e31cb55f0
children ee4537e365c8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
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 #
46819
d4ba4d51f85f contributor: change mentions of mpm to olivia
Rapha?l Gom?s <rgomes@octobus.net>
parents: 46102
diff changeset
3 # Copyright Olivia Mackall <olivia@selenic.com>
14647
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
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
9 import errno
29513
e5b4d79a9140 commandserver: backport handling of forking server from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29512
diff changeset
10 import gc
27351
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
11 import os
29513
e5b4d79a9140 commandserver: backport handling of forking server from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29512
diff changeset
12 import random
49288
311fcc5a65f6 thirdparty: remove Python 2-specific selectors2 copy
Manuel Jacob <me@manueljacob.de>
parents: 49037
diff changeset
13 import selectors
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
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
19 from .i18n import _
43089
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43077
diff changeset
20 from .pycompat import getattr
27351
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
21 from . import (
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
22 encoding,
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
23 error,
40842
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
24 loggingutil,
40636
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
25 pycompat,
41009
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 41008
diff changeset
26 repocache,
27351
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
27 util,
40842
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
28 vfs as vfsmod,
27351
28e50c4b15ed commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26587
diff changeset
29 )
37122
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36946
diff changeset
30 from .utils import (
40636
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
31 cborutil,
37122
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36946
diff changeset
32 procutil,
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36946
diff changeset
33 )
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
34
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
35
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
36 class channeledoutput:
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
37 """
22561
1120b1e2f975 cmdserver: correct doc of channeledoutput
Yuya Nishihara <yuya@tcha.org>
parents: 21195
diff changeset
38 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
39
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
40 data length (unsigned int),
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
41 data
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
42 """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
43
22563
8cc5e673cac0 cmdserver: drop useless in_ attribute from channeledoutput
Yuya Nishihara <yuya@tcha.org>
parents: 22562
diff changeset
44 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
45 self.out = out
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
46 self.channel = channel
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
47
27415
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
48 @property
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
49 def name(self):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
50 return b'<%c-channel>' % self.channel
27415
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
51
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
52 def write(self, data):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
53 if not data:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
54 return
30277
7f2313450e86 cmdserver: write channel header and payload by a single write() call
Yuya Nishihara <yuya@tcha.org>
parents: 29609
diff changeset
55 # single write() to guarantee the same atomicity as the underlying file
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
56 self.out.write(struct.pack(b'>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
57 self.out.flush()
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
58
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
59 def __getattr__(self, attr):
43554
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43089
diff changeset
60 if attr in ('isatty', 'fileno', 'tell', 'seek'):
18174
56ef99fbd6f2 commandserver: clean up use of two-argument raise
Augie Fackler <raf@durin42.com>
parents: 17425
diff changeset
61 raise AttributeError(attr)
22563
8cc5e673cac0 cmdserver: drop useless in_ attribute from channeledoutput
Yuya Nishihara <yuya@tcha.org>
parents: 22562
diff changeset
62 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
63
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
64
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
65 class channeledmessage:
40636
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
66 """
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
67 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: 40635
diff changeset
68
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
69 data length (unsigned int),
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
70 encoded message and metadata, as a flat key-value dict.
40637
83dd8c63a0c6 ui: extract helpers to write message with type or label
Yuya Nishihara <yuya@tcha.org>
parents: 40636
diff changeset
71
83dd8c63a0c6 ui: extract helpers to write message with type or label
Yuya Nishihara <yuya@tcha.org>
parents: 40636
diff changeset
72 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: 40636
diff changeset
73 should be ignored.
40636
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
74 """
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
75
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
76 # teach ui that write() can take **opts
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
77 structured = True
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
78
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
79 def __init__(self, out, channel, encodename, encodefn):
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
80 self._cout = channeledoutput(out, channel)
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
81 self.encoding = encodename
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
82 self._encodefn = encodefn
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
83
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
84 def write(self, data, **opts):
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
85 opts = pycompat.byteskwargs(opts)
40641
234c2d8c9e48 commandserver: send raw progress information to message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40637
diff changeset
86 if data is not None:
234c2d8c9e48 commandserver: send raw progress information to message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40637
diff changeset
87 opts[b'data'] = data
40636
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
88 self._cout.write(self._encodefn(opts))
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
89
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
90 def __getattr__(self, attr):
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
91 return getattr(self._cout, attr)
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
92
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
93
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
94 class channeledinput:
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
95 """
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
96 Read data from in_.
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
97
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
98 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
99 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
100 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
101
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
102 The client replies with:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
103 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
104 data
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
105 """
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
106
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
107 maxchunksize = 4 * 1024
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
108
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
109 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
110 self.in_ = in_
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
111 self.out = out
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
112 self.channel = channel
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
113
27415
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
114 @property
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
115 def name(self):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
116 return b'<%c-channel>' % self.channel
27415
f4ca33e33781 commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents: 27352
diff changeset
117
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
118 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
119 if size < 0:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
120 # 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
121 # 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
122 size = self.maxchunksize
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
123 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
124 buf = s
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
125 while s:
14728
350dcd481410 cmdserver: fix read-loop string concatenation
Idan Kamara <idankk86@gmail.com>
parents: 14719
diff changeset
126 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
127 buf += s
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
128
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
129 return buf
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
130 else:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
131 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
132
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
133 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
134 if not size:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
135 return b''
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
136 assert size > 0
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
137
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
138 # tell the client we need at most size bytes
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
139 self.out.write(struct.pack(b'>cI', channel, size))
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
140 self.out.flush()
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
141
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
142 length = self.in_.read(4)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
143 length = struct.unpack(b'>I', length)[0]
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
144 if not length:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
145 return b''
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
146 else:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
147 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
148
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
149 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
150 if size < 0:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
151 size = self.maxchunksize
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
152 s = self._read(size, b'L')
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
153 buf = s
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
154 # 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
155 # we got a full line
44187
98c14f0108b8 py3: fix EOL detection in commandserver.channeledinput
Yuya Nishihara <yuya@tcha.org>
parents: 43554
diff changeset
156 while s and not s.endswith(b'\n'):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
157 s = self._read(size, b'L')
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
158 buf += s
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
159
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
160 return buf
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
161 else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
162 return self._read(size, b'L')
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
163
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
164 def __iter__(self):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
165 return self
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
166
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
167 def next(self):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
168 l = self.readline()
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
169 if not l:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
170 raise StopIteration
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
171 return l
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
172
40358
afbfcc4e3473 py3: alias next to __next__ in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents: 40357
diff changeset
173 __next__ = next
afbfcc4e3473 py3: alias next to __next__ in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents: 40357
diff changeset
174
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
175 def __getattr__(self, attr):
43554
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43089
diff changeset
176 if attr in ('isatty', 'fileno', 'tell', 'seek'):
18174
56ef99fbd6f2 commandserver: clean up use of two-argument raise
Augie Fackler <raf@durin42.com>
parents: 17425
diff changeset
177 raise AttributeError(attr)
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
178 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
179
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
180
40636
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
181 _messageencoders = {
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
182 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: 40635
diff changeset
183 }
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
184
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
185
40636
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
186 def _selectmessageencoder(ui):
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
187 encnames = ui.configlist(b'cmdserver', b'message-encodings')
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
188 for n in encnames:
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
189 f = _messageencoders.get(n)
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
190 if f:
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
191 return n, f
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
192 raise error.Abort(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
193 b'no supported message encodings: %s' % b' '.join(encnames)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
194 )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
195
40636
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
196
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
197 class server:
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
198 """
22990
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
199 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
200 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
201 """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
202
40893
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40846
diff changeset
203 def __init__(self, ui, repo, fin, fout, prereposetups=None):
39823
24e493ec2229 py3: rename pycompat.getcwd() to encoding.getcwd() (API)
Matt Harbison <matt_harbison@yahoo.com>
parents: 38809
diff changeset
204 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
205
20650
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
206 if repo:
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
207 # 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
208 # end up with its local configuration
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
209 self.ui = repo.baseui
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
210 self.repo = repo
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
211 self.repoui = repo.ui
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
212 else:
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
213 self.ui = ui
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
214 self.repo = self.repoui = None
40893
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40846
diff changeset
215 self._prereposetups = prereposetups
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
216
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
217 self.cdebug = channeledoutput(fout, b'd')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
218 self.cerr = channeledoutput(fout, b'e')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
219 self.cout = channeledoutput(fout, b'o')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
220 self.cin = channeledinput(fin, fout, b'I')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
221 self.cresult = channeledoutput(fout, b'r')
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
222
40842
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
223 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: 40841
diff changeset
224 # 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: 40841
diff changeset
225 # (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: 40841
diff changeset
226 self.ui = self.ui.copy()
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
227 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: 40841
diff changeset
228
40636
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
229 self.cmsg = None
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
230 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: 40635
diff changeset
231 encname, encfn = _selectmessageencoder(ui)
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
232 self.cmsg = channeledmessage(fout, b'm', encname, encfn)
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
233
22990
a0e81aa94125 cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents: 22989
diff changeset
234 self.client = fin
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
235
45058
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
236 # If shutdown-on-interrupt is off, the default SIGINT handler is
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
237 # removed so that client-server communication wouldn't be interrupted.
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
238 # For example, 'runcommand' handler will issue three short read()s.
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
239 # If one of the first two read()s were interrupted, the communication
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
240 # channel would be left at dirty state and the subsequent request
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
241 # wouldn't be parsed. So catching KeyboardInterrupt isn't enough.
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
242 self._shutdown_on_interrupt = ui.configbool(
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
243 b'cmdserver', b'shutdown-on-interrupt'
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
244 )
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
245 self._old_inthandler = None
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
246 if not self._shutdown_on_interrupt:
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
247 self._old_inthandler = signal.signal(signal.SIGINT, signal.SIG_IGN)
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
248
29512
538d0003c9e0 commandserver: promote .cleanup() hook from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29511
diff changeset
249 def cleanup(self):
538d0003c9e0 commandserver: promote .cleanup() hook from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29511
diff changeset
250 """release and restore resources taken during server session"""
45058
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
251 if not self._shutdown_on_interrupt:
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
252 signal.signal(signal.SIGINT, self._old_inthandler)
29512
538d0003c9e0 commandserver: promote .cleanup() hook from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29511
diff changeset
253
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
254 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
255 if not size:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
256 return b''
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
257
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
258 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
259
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
260 # 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
261 if not data:
16687
e34106fa0dc3 cleanup: "raise SomeException()" -> "raise SomeException"
Brodie Rao <brodie@sf.io>
parents: 16683
diff changeset
262 raise EOFError
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
263
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
264 return data
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
265
28156
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
266 def _readstr(self):
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
267 """read a string from the channel
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
268
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
269 format:
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
270 data length (uint32), data
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
271 """
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
272 length = struct.unpack(b'>I', self._read(4))[0]
28156
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
273 if not length:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
274 return b''
28156
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
275 return self._read(length)
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
276
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
277 def _readlist(self):
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
278 """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
279 s = self._readstr()
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
280 if s:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
281 return s.split(b'\0')
28156
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
282 else:
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
283 return []
75f586a1bf55 commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents: 28027
diff changeset
284
45058
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
285 def _dispatchcommand(self, req):
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
286 from . import dispatch # avoid cycle
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
287
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
288 if self._shutdown_on_interrupt:
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
289 # no need to restore SIGINT handler as it is unmodified.
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
290 return dispatch.dispatch(req)
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
291
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
292 try:
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
293 signal.signal(signal.SIGINT, self._old_inthandler)
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
294 return dispatch.dispatch(req)
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
295 except error.SignalInterrupt:
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
296 # propagate SIGBREAK, SIGHUP, or SIGTERM.
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
297 raise
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
298 except KeyboardInterrupt:
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
299 # SIGINT may be received out of the try-except block of dispatch(),
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
300 # so catch it as last ditch. Another KeyboardInterrupt may be
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
301 # raised while handling exceptions here, but there's no way to
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
302 # avoid that except for doing everything in C.
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
303 pass
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
304 finally:
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
305 signal.signal(signal.SIGINT, signal.SIG_IGN)
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
306 # On KeyboardInterrupt, print error message and exit *after* SIGINT
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
307 # handler removed.
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
308 req.ui.error(_(b'interrupted!\n'))
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
309 return -1
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
310
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
311 def runcommand(self):
45957
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45682
diff changeset
312 """reads a list of \0 terminated arguments, executes
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45682
diff changeset
313 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
314 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
315
28157
e7c9b59dbbcf commandserver: use _readlist
Jun Wu <quark@fb.com>
parents: 28156
diff changeset
316 args = self._readlist()
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
317
14750
f5f97a0f983f cmdserver: copy repo.ui before running commands
Idan Kamara <idankk86@gmail.com>
parents: 14728
diff changeset
318 # 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
319 # persist between requests
14751
712954a67be3 cmdserver: assign repo.baseui before running commands
Idan Kamara <idankk86@gmail.com>
parents: 14750
diff changeset
320 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
321 uis = [copiedui]
20650
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
322 if self.repo:
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
323 self.repo.baseui = copiedui
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
324 # 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
325 repoui = self.repoui.__class__(self.repoui)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
326 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
327 uis.append(repoui)
20650
e811b93f2cb1 cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents: 20631
diff changeset
328 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
329 self.repo.invalidateall()
14751
712954a67be3 cmdserver: assign repo.baseui before running commands
Idan Kamara <idankk86@gmail.com>
parents: 14750
diff changeset
330
21195
9336bc7dca8e cmdserver: forcibly use L channel to read password input (issue3161)
Yuya Nishihara <yuya@tcha.org>
parents: 20650
diff changeset
331 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
332 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
333 # 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
334 # 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
335 # enforced only if cin is a channel.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
336 if not util.safehasattr(self.cin, b'fileno'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
337 ui.setconfig(b'ui', b'nontty', b'true', b'commandserver')
21195
9336bc7dca8e cmdserver: forcibly use L channel to read password input (issue3161)
Yuya Nishihara <yuya@tcha.org>
parents: 20650
diff changeset
338
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
339 req = dispatch.request(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
340 args[:],
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
341 copiedui,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
342 self.repo,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
343 self.cin,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
344 self.cout,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
345 self.cerr,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
346 self.cmsg,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
347 prereposetups=self._prereposetups,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
348 )
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
349
35652
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35465
diff changeset
350 try:
46102
49b6910217f9 dispatch: move IOError handling and flushing of streams to `dispatch()`
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46087
diff changeset
351 ret = self._dispatchcommand(req) & 255
45058
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
352 # If shutdown-on-interrupt is off, it's important to write the
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
353 # result code *after* SIGINT handler removed. If the result code
d6e99a446eea cmdserver: add option to not exit from message loop on SIGINT
Yuya Nishihara <yuya@tcha.org>
parents: 44407
diff changeset
354 # were lost, the client wouldn't be able to continue processing.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
355 self.cresult.write(struct.pack(b'>i', int(ret)))
35652
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35465
diff changeset
356 finally:
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35465
diff changeset
357 # restore old cwd
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
358 if b'--cwd' in args:
35652
40da2d7b4871 commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35465
diff changeset
359 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
360
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
361 def getencoding(self):
47031
f38bf44e077f black: make codebase compatible with black v21.4b2 and v20.8b1
Kyle Lippincott <spectral@google.com>
parents: 46819
diff changeset
362 """writes the current encoding to the result channel"""
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
363 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
364
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
365 def serveone(self):
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
366 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
367 if cmd:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
368 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
369 if handler:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
370 handler(self)
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
371 else:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
372 # 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
373 # looking at the servers capabilities
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
374 raise error.Abort(_(b'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
375
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
376 return cmd != b''
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
377
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
378 capabilities = {b'runcommand': runcommand, b'getencoding': getencoding}
14647
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
379
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
380 def serve(self):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
381 hellomsg = b'capabilities: ' + b' '.join(sorted(self.capabilities))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
382 hellomsg += b'\n'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
383 hellomsg += b'encoding: ' + encoding.encoding
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
384 hellomsg += b'\n'
40636
054d0fcba2c4 commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents: 40635
diff changeset
385 if self.cmsg:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
386 hellomsg += b'message-encoding: %s\n' % self.cmsg.encoding
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
387 hellomsg += b'pid: %d' % procutil.getpid()
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
388 if util.safehasattr(os, b'getpgid'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
389 hellomsg += b'\n'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
390 hellomsg += b'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
391
c19de7f32961 cmdserver: write the hello message as one chunk on the 'o' channel
Idan Kamara <idankk86@gmail.com>
parents: 14707
diff changeset
392 # 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
393 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
394
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
395 try:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
396 while self.serveone():
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
397 pass
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
398 except EOFError:
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
399 # 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
400 # its request
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
401 return 1
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
402
2e9f379de0ac serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff changeset
403 return 0
22988
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
404
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
405
40842
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
406 def setuplogging(ui, repo=None, fp=None):
40841
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40838
diff changeset
407 """Set up server logging facility
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40838
diff changeset
408
40842
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
409 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: 40841
diff changeset
410 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: 40841
diff changeset
411 is the stderr of the server process.
40841
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40838
diff changeset
412 """
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40838
diff changeset
413 # developer config: cmdserver.log
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40838
diff changeset
414 logpath = ui.config(b'cmdserver', b'log')
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40838
diff changeset
415 if not logpath:
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40838
diff changeset
416 return
40845
d23fd01cc115 commandserver: add config knob for various logging options
Yuya Nishihara <yuya@tcha.org>
parents: 40844
diff changeset
417 # developer config: cmdserver.track-log
d23fd01cc115 commandserver: add config knob for various logging options
Yuya Nishihara <yuya@tcha.org>
parents: 40844
diff changeset
418 tracked = set(ui.configlist(b'cmdserver', b'track-log'))
40841
368ecbf734af commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents: 40838
diff changeset
419
40842
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
420 if logpath == b'-' and fp:
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
421 logger = loggingutil.fileobjectlogger(fp, tracked)
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
422 elif logpath == b'-':
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
423 logger = loggingutil.fileobjectlogger(ui.ferr, tracked)
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
424 else:
47624
27e75b8bf784 windows: use abspath in commandserver
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47031
diff changeset
425 logpath = util.abspath(util.expandpath(logpath))
40845
d23fd01cc115 commandserver: add config knob for various logging options
Yuya Nishihara <yuya@tcha.org>
parents: 40844
diff changeset
426 # developer config: cmdserver.max-log-files
d23fd01cc115 commandserver: add config knob for various logging options
Yuya Nishihara <yuya@tcha.org>
parents: 40844
diff changeset
427 maxfiles = ui.configint(b'cmdserver', b'max-log-files')
d23fd01cc115 commandserver: add config knob for various logging options
Yuya Nishihara <yuya@tcha.org>
parents: 40844
diff changeset
428 # developer config: cmdserver.max-log-size
d23fd01cc115 commandserver: add config knob for various logging options
Yuya Nishihara <yuya@tcha.org>
parents: 40844
diff changeset
429 maxsize = ui.configbytes(b'cmdserver', b'max-log-size')
40842
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
430 vfs = vfsmod.vfs(os.path.dirname(logpath))
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
431 logger = loggingutil.filelogger(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
432 vfs,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
433 os.path.basename(logpath),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
434 tracked,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
435 maxfiles=maxfiles,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
436 maxsize=maxsize,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
437 )
40842
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
438
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
439 targetuis = {ui}
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
440 if repo:
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
441 targetuis.add(repo.baseui)
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
442 targetuis.add(repo.ui)
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
443 for u in targetuis:
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
444 u.setlogger(b'cmdserver', logger)
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40841
diff changeset
445
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
446
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
447 class pipeservice:
22988
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
448 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
449 self.ui = ui
bc374458688b cmdserver: postpone creation of pipe server until run()
Yuya Nishihara <yuya@tcha.org>
parents: 23322
diff changeset
450 self.repo = repo
22988
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
451
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
452 def init(self):
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
453 pass
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
454
32b77aba2772 cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents: 22563
diff changeset
455 def run(self):
23323
bc374458688b cmdserver: postpone creation of pipe server until run()
Yuya Nishihara <yuya@tcha.org>
parents: 23322
diff changeset
456 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
457 # 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
458 # hooks will never cause corruption of channel protocol.
41284
b0e3f2d7c143 ui: move protectedstdio() context manager from procutil
Yuya Nishihara <yuya@tcha.org>
parents: 41009
diff changeset
459 with ui.protectedfinout() as (fin, fout):
40635
9683dfb6f13a commandserver: fix reference before assignment error in pipeservice cleanup
Yuya Nishihara <yuya@tcha.org>
parents: 40361
diff changeset
460 sv = server(ui, self.repo, fin, fout)
37127
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37126
diff changeset
461 try:
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37126
diff changeset
462 return sv.serve()
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37126
diff changeset
463 finally:
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37126
diff changeset
464 sv.cleanup()
22989
dc8803ce3dfe cmdserver: switch service objects by mode
Yuya Nishihara <yuya@tcha.org>
parents: 22988
diff changeset
465
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
466
29586
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
467 def _initworkerprocess():
29609
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
468 # 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
469 # 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
470 # 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
471 # remains in a same session)
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
472 # 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
473 # 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
474 # cause trouble for things like ncurses.
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
475 # 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
476 # 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
477 # processes like ssh will be killed properly, without affecting
591c3badff2e commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents: 29588
diff changeset
478 # unrelated processes.
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
479 os.setpgid(0, 0)
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
480 # 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
481 # same state inherited from parent.
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
482 random.seed()
29542
6011ad3b0a42 commandserver: manually create file objects from socket
Yuya Nishihara <yuya@tcha.org>
parents: 29532
diff changeset
483
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
484
40893
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40846
diff changeset
485 def _serverequest(ui, repo, conn, createcmdserver, prereposetups):
43554
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43089
diff changeset
486 fin = conn.makefile('rb')
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43089
diff changeset
487 fout = conn.makefile('wb')
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
488 sv = None
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
489 try:
40893
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40846
diff changeset
490 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
491 try:
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
492 sv.serve()
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
493 # 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
494 # known exceptions are caught by dispatch.
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
495 except error.Abort as inst:
45682
d2e1dcd4490d errors: name arguments to Abort constructor
Martin von Zweigbergk <martinvonz@google.com>
parents: 45059
diff changeset
496 ui.error(_(b'abort: %s\n') % inst.message)
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
497 except IOError as inst:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
498 if inst.errno != errno.EPIPE:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
499 raise
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
500 except KeyboardInterrupt:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
501 pass
29513
e5b4d79a9140 commandserver: backport handling of forking server from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29512
diff changeset
502 finally:
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
503 sv.cleanup()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
504 except: # re-raises
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
505 # 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
506 # 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
507 if sv:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
508 cerr = sv.cerr
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
509 else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
510 cerr = channeledoutput(fout, b'e')
40361
b7de186efd82 py3: don't use traceback.print_exc() in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents: 40359
diff changeset
511 cerr.write(encoding.strtolocal(traceback.format_exc()))
29585
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
512 raise
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
513 finally:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
514 fin.close()
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
515 try:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
516 fout.close() # implicit flush() may cause another EPIPE
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
517 except IOError as inst:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
518 if inst.errno != errno.EPIPE:
6ed452d0f1f1 commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 29580
diff changeset
519 raise
22994
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
520
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
521
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
522 class unixservicehandler:
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
523 """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
524
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
525 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
526 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
527 """
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
528
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
529 pollinterval = None
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
530
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
531 def __init__(self, ui):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
532 self.ui = ui
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
533
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
534 def bindsocket(self, sock, address):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
535 util.bindunixsocket(sock, address)
32276
c8b9943c07eb commandserver: move "listen" responsibility from service to handler
Jun Wu <quark@fb.com>
parents: 30944
diff changeset
536 sock.listen(socket.SOMAXCONN)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
537 self.ui.status(_(b'listening at %s\n') % address)
32277
1ada3d18e7fb commandserver: move printbanner logic to bindsocket
Jun Wu <quark@fb.com>
parents: 32276
diff changeset
538 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
539
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
540 def unlinksocket(self, address):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
541 os.unlink(address)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
542
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
543 def shouldexit(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
544 """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
545 return False
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
546
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
547 def newconnection(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
548 """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
549
40893
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40846
diff changeset
550 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
551 """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
552 serves for the current connection"""
40893
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40846
diff changeset
553 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
554
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
555
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
556 class unixforkingservice:
22994
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
557 """
840be5ca03e1 cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents: 22990
diff changeset
558 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
559 """
29548
9da1adc18639 commandserver: drop old unixservice implementation
Yuya Nishihara <yuya@tcha.org>
parents: 29544
diff changeset
560
9da1adc18639 commandserver: drop old unixservice implementation
Yuya Nishihara <yuya@tcha.org>
parents: 29544
diff changeset
561 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
562 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
563 self.repo = repo
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
564 self.address = opts[b'address']
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
565 if not util.safehasattr(socket, b'AF_UNIX'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
566 raise error.Abort(_(b'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
567 if not self.address:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
568 raise error.Abort(_(b'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
569 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
570 self._sock = None
41008
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
571 self._mainipc = None
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
572 self._workeripc = None
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
573 self._oldsigchldhandler = None
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
574 self._workerpids = set() # updated by signal handler; do not iterate
30919
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30528
diff changeset
575 self._socketunlinked = None
41009
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 41008
diff changeset
576 # experimental config: cmdserver.max-repo-cache
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 41008
diff changeset
577 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: 41008
diff changeset
578 if maxlen < 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
579 raise error.Abort(_(b'negative max-repo-cache size not allowed'))
41009
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 41008
diff changeset
580 self._repoloader = repocache.repoloader(ui, maxlen)
44402
6392bd7c26a8 darwin: add another preemptive gui() call when using chg
Kyle Lippincott <spectral@google.com>
parents: 43554
diff changeset
581 # attempt to avoid crash in CoreFoundation when using chg after fix in
6392bd7c26a8 darwin: add another preemptive gui() call when using chg
Kyle Lippincott <spectral@google.com>
parents: 43554
diff changeset
582 # a89381e04c58
6392bd7c26a8 darwin: add another preemptive gui() call when using chg
Kyle Lippincott <spectral@google.com>
parents: 43554
diff changeset
583 if pycompat.isdarwin:
6392bd7c26a8 darwin: add another preemptive gui() call when using chg
Kyle Lippincott <spectral@google.com>
parents: 43554
diff changeset
584 procutil.gui()
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
585
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
586 def init(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
587 self._sock = socket.socket(socket.AF_UNIX)
41008
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
588 # 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: 40896
diff changeset
589 # 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: 40896
diff changeset
590 # message can be easily separated.
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
591 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: 40896
diff changeset
592 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
593 self._servicehandler.bindsocket(self._sock, self.address)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
594 if util.safehasattr(procutil, b'unblocksignal'):
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37122
diff changeset
595 procutil.unblocksignal(signal.SIGCHLD)
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
596 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
597 self._oldsigchldhandler = o
30919
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30528
diff changeset
598 self._socketunlinked = False
41009
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 41008
diff changeset
599 self._repoloader.start()
30919
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30528
diff changeset
600
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30528
diff changeset
601 def _unlinksocket(self):
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30528
diff changeset
602 if not self._socketunlinked:
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30528
diff changeset
603 self._servicehandler.unlinksocket(self.address)
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30528
diff changeset
604 self._socketunlinked = True
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
605
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
606 def _cleanup(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
607 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
608 self._sock.close()
41008
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
609 self._mainipc.close()
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
610 self._workeripc.close()
30919
a95fc01aaffe commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents: 30528
diff changeset
611 self._unlinksocket()
41009
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 41008
diff changeset
612 self._repoloader.stop()
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
613 # 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
614 self._reapworkers(0)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
615
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
616 def run(self):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
617 try:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
618 self._mainloop()
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
619 finally:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
620 self._cleanup()
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
621
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
622 def _mainloop(self):
30920
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30919
diff changeset
623 exiting = False
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
624 h = self._servicehandler
36946
b0ffcb540357 commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents: 36843
diff changeset
625 selector = selectors.DefaultSelector()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
626 selector.register(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
627 self._sock, selectors.EVENT_READ, self._acceptnewconnection
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
628 )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
629 selector.register(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
630 self._mainipc, selectors.EVENT_READ, self._handlemainipc
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
631 )
30920
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30919
diff changeset
632 while True:
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30919
diff changeset
633 if not exiting and h.shouldexit():
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30919
diff changeset
634 # clients can no longer connect() to the domain socket, so
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30919
diff changeset
635 # we stop queuing new requests.
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30919
diff changeset
636 # for requests that are queued (connect()-ed, but haven't been
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30919
diff changeset
637 # accept()-ed), handle them before exit. otherwise, clients
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30919
diff changeset
638 # waiting for recv() will receive ECONNRESET.
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30919
diff changeset
639 self._unlinksocket()
b1b36c6499c2 commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents: 30919
diff changeset
640 exiting = True
49288
311fcc5a65f6 thirdparty: remove Python 2-specific selectors2 copy
Manuel Jacob <me@manueljacob.de>
parents: 49037
diff changeset
641 events = selector.select(timeout=h.pollinterval)
40896
2525faf4ecdb commandserver: loop over selector events
Yuya Nishihara <yuya@tcha.org>
parents: 40895
diff changeset
642 if not events:
33543
3ef3bf704e47 commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents: 33506
diff changeset
643 # 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
644 if exiting:
3ef3bf704e47 commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents: 33506
diff changeset
645 break
3ef3bf704e47 commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents: 33506
diff changeset
646 continue
40896
2525faf4ecdb commandserver: loop over selector events
Yuya Nishihara <yuya@tcha.org>
parents: 40895
diff changeset
647 for key, _mask in events:
2525faf4ecdb commandserver: loop over selector events
Yuya Nishihara <yuya@tcha.org>
parents: 40895
diff changeset
648 key.data(key.fileobj, selector)
40894
dc9901558e3c commandserver: extract handler of new socket connection
Yuya Nishihara <yuya@tcha.org>
parents: 40893
diff changeset
649 selector.close()
dc9901558e3c commandserver: extract handler of new socket connection
Yuya Nishihara <yuya@tcha.org>
parents: 40893
diff changeset
650
dc9901558e3c commandserver: extract handler of new socket connection
Yuya Nishihara <yuya@tcha.org>
parents: 40893
diff changeset
651 def _acceptnewconnection(self, sock, selector):
dc9901558e3c commandserver: extract handler of new socket connection
Yuya Nishihara <yuya@tcha.org>
parents: 40893
diff changeset
652 h = self._servicehandler
40895
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
653 try:
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
654 conn, _addr = sock.accept()
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
655 except socket.error as inst:
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
656 if inst.args[0] == errno.EINTR:
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
657 return
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
658 raise
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
659
41009
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 41008
diff changeset
660 # 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: 41008
diff changeset
661 # 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: 41008
diff changeset
662 # https://instagram-engineering.com/
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 41008
diff changeset
663 # copy-on-write-friendly-python-garbage-collection-ad6ed5233ddf
40895
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
664 pid = os.fork()
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
665 if pid:
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
666 try:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
667 self.ui.log(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
668 b'cmdserver', b'forked worker process (pid=%d)\n', pid
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
669 )
40895
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
670 self._workerpids.add(pid)
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
671 h.newconnection()
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
672 finally:
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
673 conn.close() # release handle in parent process
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
674 else:
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
675 try:
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
676 selector.close()
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
677 sock.close()
41008
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
678 self._mainipc.close()
40895
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
679 self._runworker(conn)
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
680 conn.close()
41008
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
681 self._workeripc.close()
40895
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
682 os._exit(0)
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
683 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
684 try:
40895
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
685 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
686 finally:
40895
9f00de4dc7cb commandserver: remove redundant "if True" block
Yuya Nishihara <yuya@tcha.org>
parents: 40894
diff changeset
687 os._exit(255)
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
688
41008
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
689 def _handlemainipc(self, sock, selector):
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
690 """Process messages sent from a worker"""
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
691 try:
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
692 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: 40896
diff changeset
693 except socket.error as inst:
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
694 if inst.args[0] == errno.EINTR:
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
695 return
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
696 raise
41009
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 41008
diff changeset
697 self._repoloader.load(path)
41008
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
698
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
699 def _sigchldhandler(self, signal, frame):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
700 self._reapworkers(os.WNOHANG)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
701
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
702 def _reapworkers(self, options):
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
703 while self._workerpids:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
704 try:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
705 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
706 except OSError as inst:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
707 if inst.errno == errno.EINTR:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
708 continue
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
709 if inst.errno != errno.ECHILD:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
710 raise
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
711 # 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
712 self._workerpids.clear()
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
713 return
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
714 if pid == 0:
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
715 # no waitable child processes
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
716 return
40846
25e9089c7686 commandserver: turn server debug messages into logs
Yuya Nishihara <yuya@tcha.org>
parents: 40845
diff changeset
717 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
718 self._workerpids.discard(pid)
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
719
29587
536eec443b4a commandserver: rename _serveworker() to _runworker()
Yuya Nishihara <yuya@tcha.org>
parents: 29586
diff changeset
720 def _runworker(self, conn):
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
721 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
722 _initworkerprocess()
29544
024e8f82f3de commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
723 h = self._servicehandler
29586
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
724 try:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
725 _serverequest(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
726 self.ui,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
727 self.repo,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
728 conn,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
729 h.createcmdserver,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
730 prereposetups=[self._reposetup],
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
731 )
29586
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
732 finally:
42cdba9cfee4 commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents: 29585
diff changeset
733 gc.collect() # trigger __del__ since worker process uses os._exit
41008
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
734
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
735 def _reposetup(self, ui, repo):
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
736 if not repo.local():
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
737 return
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
738
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
739 class unixcmdserverrepo(repo.__class__):
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
740 def close(self):
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
741 super(unixcmdserverrepo, self).close()
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
742 try:
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
743 self._cmdserveripc.send(self.root)
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
744 except socket.error:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
745 self.ui.log(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41284
diff changeset
746 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
747 )
41008
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
748
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
749 repo.__class__ = unixcmdserverrepo
042ed354b9eb commandserver: add IPC channel to teach repository path on command finished
Yuya Nishihara <yuya@tcha.org>
parents: 40896
diff changeset
750 repo._cmdserveripc = self._workeripc
41009
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 41008
diff changeset
751
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 41008
diff changeset
752 cachedrepo = self._repoloader.get(repo.root)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 41008
diff changeset
753 if cachedrepo is None:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 41008
diff changeset
754 return
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents: 41008
diff changeset
755 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: 41008
diff changeset
756 repocache.copycache(cachedrepo, repo)