Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/commandserver.py @ 40842:82210d88d814
commandserver: install logger to record server events through canonical API
The global commandserver.log() will be replaced with this.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sat, 10 Nov 2018 19:00:17 +0900 |
parents | 368ecbf734af |
children | eaabcb689747 |
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 # |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
3 # Copyright Matt Mackall <mpm@selenic.com> |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
4 # |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
6 # GNU General Public License version 2 or any later version. |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
7 |
27351
28e50c4b15ed
commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
26587
diff
changeset
|
8 from __future__ import absolute_import |
28e50c4b15ed
commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
26587
diff
changeset
|
9 |
28e50c4b15ed
commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
26587
diff
changeset
|
10 import errno |
29513
e5b4d79a9140
commandserver: backport handling of forking server from chgserver
Yuya Nishihara <yuya@tcha.org>
parents:
29512
diff
changeset
|
11 import gc |
27351
28e50c4b15ed
commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
26587
diff
changeset
|
12 import os |
29513
e5b4d79a9140
commandserver: backport handling of forking server from chgserver
Yuya Nishihara <yuya@tcha.org>
parents:
29512
diff
changeset
|
13 import random |
29544
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
14 import signal |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
15 import socket |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
16 import struct |
27351
28e50c4b15ed
commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
26587
diff
changeset
|
17 import traceback |
28e50c4b15ed
commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
26587
diff
changeset
|
18 |
36946
b0ffcb540357
commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents:
36843
diff
changeset
|
19 try: |
b0ffcb540357
commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents:
36843
diff
changeset
|
20 import selectors |
b0ffcb540357
commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents:
36843
diff
changeset
|
21 selectors.BaseSelector |
b0ffcb540357
commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents:
36843
diff
changeset
|
22 except ImportError: |
b0ffcb540357
commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents:
36843
diff
changeset
|
23 from .thirdparty import selectors2 as selectors |
b0ffcb540357
commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents:
36843
diff
changeset
|
24 |
27351
28e50c4b15ed
commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
26587
diff
changeset
|
25 from .i18n import _ |
28e50c4b15ed
commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
26587
diff
changeset
|
26 from . import ( |
28e50c4b15ed
commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
26587
diff
changeset
|
27 encoding, |
28e50c4b15ed
commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
26587
diff
changeset
|
28 error, |
40842
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
29 loggingutil, |
40636
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
30 pycompat, |
27351
28e50c4b15ed
commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
26587
diff
changeset
|
31 util, |
40842
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
32 vfs as vfsmod, |
27351
28e50c4b15ed
commandserver: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
26587
diff
changeset
|
33 ) |
37122
d4a2e0d5d042
procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36946
diff
changeset
|
34 from .utils import ( |
40636
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
35 cborutil, |
37122
d4a2e0d5d042
procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36946
diff
changeset
|
36 procutil, |
d4a2e0d5d042
procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36946
diff
changeset
|
37 ) |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
38 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
39 logfile = None |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
40 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
41 def log(*args): |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
42 if not logfile: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
43 return |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
44 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
45 for a in args: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
46 logfile.write(str(a)) |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
47 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
48 logfile.flush() |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
49 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
50 class channeledoutput(object): |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
51 """ |
22561
1120b1e2f975
cmdserver: correct doc of channeledoutput
Yuya Nishihara <yuya@tcha.org>
parents:
21195
diff
changeset
|
52 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
|
53 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
54 data length (unsigned int), |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
55 data |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
56 """ |
22563
8cc5e673cac0
cmdserver: drop useless in_ attribute from channeledoutput
Yuya Nishihara <yuya@tcha.org>
parents:
22562
diff
changeset
|
57 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
|
58 self.out = out |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
59 self.channel = channel |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
60 |
27415
f4ca33e33781
commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents:
27352
diff
changeset
|
61 @property |
f4ca33e33781
commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents:
27352
diff
changeset
|
62 def name(self): |
f4ca33e33781
commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents:
27352
diff
changeset
|
63 return '<%c-channel>' % self.channel |
f4ca33e33781
commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents:
27352
diff
changeset
|
64 |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
65 def write(self, data): |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
66 if not data: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
67 return |
30277
7f2313450e86
cmdserver: write channel header and payload by a single write() call
Yuya Nishihara <yuya@tcha.org>
parents:
29609
diff
changeset
|
68 # single write() to guarantee the same atomicity as the underlying file |
7f2313450e86
cmdserver: write channel header and payload by a single write() call
Yuya Nishihara <yuya@tcha.org>
parents:
29609
diff
changeset
|
69 self.out.write(struct.pack('>cI', self.channel, len(data)) + data) |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
70 self.out.flush() |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
71 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
72 def __getattr__(self, attr): |
40357
efbf7de09d2a
py3: system-stringify list of attributes to be forwarded from commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents:
39823
diff
changeset
|
73 if attr in (r'isatty', r'fileno', r'tell', r'seek'): |
18174
56ef99fbd6f2
commandserver: clean up use of two-argument raise
Augie Fackler <raf@durin42.com>
parents:
17425
diff
changeset
|
74 raise AttributeError(attr) |
22563
8cc5e673cac0
cmdserver: drop useless in_ attribute from channeledoutput
Yuya Nishihara <yuya@tcha.org>
parents:
22562
diff
changeset
|
75 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
|
76 |
40636
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
77 class channeledmessage(object): |
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 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
|
80 |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
81 data length (unsigned int), |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
82 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
|
83 |
83dd8c63a0c6
ui: extract helpers to write message with type or label
Yuya Nishihara <yuya@tcha.org>
parents:
40636
diff
changeset
|
84 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
|
85 should be ignored. |
40636
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
86 """ |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
87 |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
88 # 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
|
89 structured = True |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
90 |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
91 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
|
92 self._cout = channeledoutput(out, channel) |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
93 self.encoding = encodename |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
94 self._encodefn = encodefn |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
95 |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
96 def write(self, data, **opts): |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
97 opts = pycompat.byteskwargs(opts) |
40641
234c2d8c9e48
commandserver: send raw progress information to message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40637
diff
changeset
|
98 if data is not None: |
234c2d8c9e48
commandserver: send raw progress information to message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40637
diff
changeset
|
99 opts[b'data'] = data |
40636
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
100 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
|
101 |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
102 def __getattr__(self, attr): |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
103 return getattr(self._cout, attr) |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
104 |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
105 class channeledinput(object): |
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 Read data from in_. |
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 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
|
110 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
|
111 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
|
112 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
113 The client replies with: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
114 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
|
115 data |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
116 """ |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
117 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
118 maxchunksize = 4 * 1024 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
119 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
120 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
|
121 self.in_ = in_ |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
122 self.out = out |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
123 self.channel = channel |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
124 |
27415
f4ca33e33781
commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents:
27352
diff
changeset
|
125 @property |
f4ca33e33781
commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents:
27352
diff
changeset
|
126 def name(self): |
f4ca33e33781
commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents:
27352
diff
changeset
|
127 return '<%c-channel>' % self.channel |
f4ca33e33781
commandserver: implement name() to clarify channel is not a plain file
Yuya Nishihara <yuya@tcha.org>
parents:
27352
diff
changeset
|
128 |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
129 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
|
130 if size < 0: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
131 # 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
|
132 # 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
|
133 size = self.maxchunksize |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
134 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
|
135 buf = s |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
136 while s: |
14728
350dcd481410
cmdserver: fix read-loop string concatenation
Idan Kamara <idankk86@gmail.com>
parents:
14719
diff
changeset
|
137 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
|
138 buf += s |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
139 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
140 return buf |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
141 else: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
142 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
|
143 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
144 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
|
145 if not size: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
146 return '' |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
147 assert size > 0 |
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 # tell the client we need at most size bytes |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
150 self.out.write(struct.pack('>cI', channel, size)) |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
151 self.out.flush() |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
152 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
153 length = self.in_.read(4) |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
154 length = struct.unpack('>I', length)[0] |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
155 if not length: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
156 return '' |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
157 else: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
158 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
|
159 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
160 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
|
161 if size < 0: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
162 size = self.maxchunksize |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
163 s = self._read(size, 'L') |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
164 buf = s |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
165 # 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
|
166 # we got a full line |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
167 while s and s[-1] != '\n': |
14728
350dcd481410
cmdserver: fix read-loop string concatenation
Idan Kamara <idankk86@gmail.com>
parents:
14719
diff
changeset
|
168 s = self._read(size, 'L') |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
169 buf += s |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
170 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
171 return buf |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
172 else: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
173 return self._read(size, 'L') |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
174 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
175 def __iter__(self): |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
176 return self |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
177 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
178 def next(self): |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
179 l = self.readline() |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
180 if not l: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
181 raise StopIteration |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
182 return l |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
183 |
40358
afbfcc4e3473
py3: alias next to __next__ in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents:
40357
diff
changeset
|
184 __next__ = next |
afbfcc4e3473
py3: alias next to __next__ in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents:
40357
diff
changeset
|
185 |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
186 def __getattr__(self, attr): |
40357
efbf7de09d2a
py3: system-stringify list of attributes to be forwarded from commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents:
39823
diff
changeset
|
187 if attr in (r'isatty', r'fileno', r'tell', r'seek'): |
18174
56ef99fbd6f2
commandserver: clean up use of two-argument raise
Augie Fackler <raf@durin42.com>
parents:
17425
diff
changeset
|
188 raise AttributeError(attr) |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
189 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
|
190 |
40636
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
191 _messageencoders = { |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
192 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
|
193 } |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
194 |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
195 def _selectmessageencoder(ui): |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
196 # experimental config: cmdserver.message-encodings |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
197 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
|
198 for n in encnames: |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
199 f = _messageencoders.get(n) |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
200 if f: |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
201 return n, f |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
202 raise error.Abort(b'no supported message encodings: %s' |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
203 % b' '.join(encnames)) |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
204 |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
205 class server(object): |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
206 """ |
22990
a0e81aa94125
cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents:
22989
diff
changeset
|
207 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
|
208 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
|
209 """ |
22990
a0e81aa94125
cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents:
22989
diff
changeset
|
210 def __init__(self, ui, repo, fin, fout): |
39823
24e493ec2229
py3: rename pycompat.getcwd() to encoding.getcwd() (API)
Matt Harbison <matt_harbison@yahoo.com>
parents:
38809
diff
changeset
|
211 self.cwd = encoding.getcwd() |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
212 |
40841
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
213 if ui.config("cmdserver", "log") == '-': |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
214 global logfile |
40841
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
215 # switch log stream to the 'd' (debug) channel |
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
216 logfile = channeledoutput(fout, 'd') |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
217 |
20650
e811b93f2cb1
cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents:
20631
diff
changeset
|
218 if repo: |
e811b93f2cb1
cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents:
20631
diff
changeset
|
219 # 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
|
220 # end up with its local configuration |
e811b93f2cb1
cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents:
20631
diff
changeset
|
221 self.ui = repo.baseui |
e811b93f2cb1
cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents:
20631
diff
changeset
|
222 self.repo = repo |
e811b93f2cb1
cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents:
20631
diff
changeset
|
223 self.repoui = repo.ui |
e811b93f2cb1
cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents:
20631
diff
changeset
|
224 else: |
e811b93f2cb1
cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents:
20631
diff
changeset
|
225 self.ui = ui |
e811b93f2cb1
cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents:
20631
diff
changeset
|
226 self.repo = self.repoui = None |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
227 |
40842
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
228 self.cdebug = logfile |
22990
a0e81aa94125
cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents:
22989
diff
changeset
|
229 self.cerr = channeledoutput(fout, 'e') |
a0e81aa94125
cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents:
22989
diff
changeset
|
230 self.cout = channeledoutput(fout, 'o') |
a0e81aa94125
cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents:
22989
diff
changeset
|
231 self.cin = channeledinput(fin, fout, 'I') |
a0e81aa94125
cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents:
22989
diff
changeset
|
232 self.cresult = channeledoutput(fout, 'r') |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
233 |
40842
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
234 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
|
235 # 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
|
236 # (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
|
237 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
|
238 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
|
239 |
40636
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
240 # TODO: add this to help/config.txt when stabilized |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
241 # ``channel`` |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
242 # Use separate channel for structured output. (Command-server only) |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
243 self.cmsg = None |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
244 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
|
245 encname, encfn = _selectmessageencoder(ui) |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
246 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
|
247 |
22990
a0e81aa94125
cmdserver: make server streams switchable
Yuya Nishihara <yuya@tcha.org>
parents:
22989
diff
changeset
|
248 self.client = fin |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
249 |
29512
538d0003c9e0
commandserver: promote .cleanup() hook from chgserver
Yuya Nishihara <yuya@tcha.org>
parents:
29511
diff
changeset
|
250 def cleanup(self): |
538d0003c9e0
commandserver: promote .cleanup() hook from chgserver
Yuya Nishihara <yuya@tcha.org>
parents:
29511
diff
changeset
|
251 """release and restore resources taken during server session""" |
538d0003c9e0
commandserver: promote .cleanup() hook from chgserver
Yuya Nishihara <yuya@tcha.org>
parents:
29511
diff
changeset
|
252 |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
253 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
|
254 if not size: |
5fd5dd9a610a
cmdserver: don't raise EOFError when trying to read 0 bytes from the client
Idan Kamara <idankk86@gmail.com>
parents:
14647
diff
changeset
|
255 return '' |
5fd5dd9a610a
cmdserver: don't raise EOFError when trying to read 0 bytes from the client
Idan Kamara <idankk86@gmail.com>
parents:
14647
diff
changeset
|
256 |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
257 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
|
258 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
259 # 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
|
260 if not data: |
16687
e34106fa0dc3
cleanup: "raise SomeException()" -> "raise SomeException"
Brodie Rao <brodie@sf.io>
parents:
16683
diff
changeset
|
261 raise EOFError |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
262 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
263 return data |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
264 |
28156
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
265 def _readstr(self): |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
266 """read a string from the channel |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
267 |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
268 format: |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
269 data length (uint32), data |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
270 """ |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
271 length = struct.unpack('>I', self._read(4))[0] |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
272 if not length: |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
273 return '' |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
274 return self._read(length) |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
275 |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
276 def _readlist(self): |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
277 """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
|
278 s = self._readstr() |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
279 if s: |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
280 return s.split('\0') |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
281 else: |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
282 return [] |
75f586a1bf55
commandserver: add _readstr and _readlist
Jun Wu <quark@fb.com>
parents:
28027
diff
changeset
|
283 |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
284 def runcommand(self): |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
285 """ reads a list of \0 terminated arguments, executes |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
286 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
|
287 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
|
288 |
28157 | 289 args = self._readlist() |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
290 |
14750
f5f97a0f983f
cmdserver: copy repo.ui before running commands
Idan Kamara <idankk86@gmail.com>
parents:
14728
diff
changeset
|
291 # 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
|
292 # persist between requests |
14751
712954a67be3
cmdserver: assign repo.baseui before running commands
Idan Kamara <idankk86@gmail.com>
parents:
14750
diff
changeset
|
293 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
|
294 uis = [copiedui] |
20650
e811b93f2cb1
cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents:
20631
diff
changeset
|
295 if self.repo: |
e811b93f2cb1
cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents:
20631
diff
changeset
|
296 self.repo.baseui = copiedui |
e811b93f2cb1
cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents:
20631
diff
changeset
|
297 # 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
|
298 repoui = self.repoui.__class__(self.repoui) |
e811b93f2cb1
cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents:
20631
diff
changeset
|
299 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
|
300 uis.append(repoui) |
20650
e811b93f2cb1
cmdserver: allow to start server without repository
Yuya Nishihara <yuya@tcha.org>
parents:
20631
diff
changeset
|
301 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
|
302 self.repo.invalidateall() |
14751
712954a67be3
cmdserver: assign repo.baseui before running commands
Idan Kamara <idankk86@gmail.com>
parents:
14750
diff
changeset
|
303 |
21195
9336bc7dca8e
cmdserver: forcibly use L channel to read password input (issue3161)
Yuya Nishihara <yuya@tcha.org>
parents:
20650
diff
changeset
|
304 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
|
305 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
|
306 # 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
|
307 # 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
|
308 # enforced only if cin is a channel. |
e7937438e3f7
commandserver: do not set nontty flag if channel is replaced by a real file
Yuya Nishihara <yuya@tcha.org>
parents:
27415
diff
changeset
|
309 if not util.safehasattr(self.cin, 'fileno'): |
e7937438e3f7
commandserver: do not set nontty flag if channel is replaced by a real file
Yuya Nishihara <yuya@tcha.org>
parents:
27415
diff
changeset
|
310 ui.setconfig('ui', 'nontty', 'true', 'commandserver') |
21195
9336bc7dca8e
cmdserver: forcibly use L channel to read password input (issue3161)
Yuya Nishihara <yuya@tcha.org>
parents:
20650
diff
changeset
|
311 |
14864
1b872599f39f
cmdserver: restore old working dir after dispatch when we have --cwd
Idan Kamara <idankk86@gmail.com>
parents:
14751
diff
changeset
|
312 req = dispatch.request(args[:], copiedui, self.repo, self.cin, |
40636
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
313 self.cout, self.cerr, self.cmsg) |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
314 |
35652
40da2d7b4871
commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35465
diff
changeset
|
315 try: |
38038
6f9ac3cb0987
dispatch: unify handling of None returned by a command function
Yuya Nishihara <yuya@tcha.org>
parents:
37127
diff
changeset
|
316 ret = dispatch.dispatch(req) & 255 |
35652
40da2d7b4871
commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35465
diff
changeset
|
317 self.cresult.write(struct.pack('>i', int(ret))) |
40da2d7b4871
commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35465
diff
changeset
|
318 finally: |
40da2d7b4871
commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35465
diff
changeset
|
319 # restore old cwd |
40da2d7b4871
commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35465
diff
changeset
|
320 if '--cwd' in args: |
40da2d7b4871
commandserver: restore cwd in case of exception
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35465
diff
changeset
|
321 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
|
322 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
323 def getencoding(self): |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
324 """ writes the current encoding to the result channel """ |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
325 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
|
326 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
327 def serveone(self): |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
328 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
|
329 if cmd: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
330 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
|
331 if handler: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
332 handler(self) |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
333 else: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
334 # 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
|
335 # looking at the servers capabilities |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25832
diff
changeset
|
336 raise error.Abort(_('unknown command %s') % cmd) |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
337 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
338 return cmd != '' |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
339 |
34486
a57c938e7ac8
style: never use a space before a colon or comma
Alex Gaynor <agaynor@mozilla.com>
parents:
34374
diff
changeset
|
340 capabilities = {'runcommand': runcommand, |
a57c938e7ac8
style: never use a space before a colon or comma
Alex Gaynor <agaynor@mozilla.com>
parents:
34374
diff
changeset
|
341 'getencoding': getencoding} |
14647
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
342 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
343 def serve(self): |
18359
4b09e6f7d7de
commandserver: report capabilities sorted
Mads Kiilerich <mads@kiilerich.com>
parents:
18174
diff
changeset
|
344 hellomsg = 'capabilities: ' + ' '.join(sorted(self.capabilities)) |
14719
c19de7f32961
cmdserver: write the hello message as one chunk on the 'o' channel
Idan Kamara <idankk86@gmail.com>
parents:
14707
diff
changeset
|
345 hellomsg += '\n' |
c19de7f32961
cmdserver: write the hello message as one chunk on the 'o' channel
Idan Kamara <idankk86@gmail.com>
parents:
14707
diff
changeset
|
346 hellomsg += 'encoding: ' + encoding.encoding |
23036
19f5273c9f3e
cmdserver: include pid of server handling requests in hello message
Yuya Nishihara <yuya@tcha.org>
parents:
22994
diff
changeset
|
347 hellomsg += '\n' |
40636
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
348 if self.cmsg: |
054d0fcba2c4
commandserver: add experimental option to use separate message channel
Yuya Nishihara <yuya@tcha.org>
parents:
40635
diff
changeset
|
349 hellomsg += 'message-encoding: %s\n' % self.cmsg.encoding |
37123
a8a902d7176e
procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
37122
diff
changeset
|
350 hellomsg += 'pid: %d' % procutil.getpid() |
29580
ee8186457516
commandserver: send pgid in hello message
Jun Wu <quark@fb.com>
parents:
29548
diff
changeset
|
351 if util.safehasattr(os, 'getpgid'): |
ee8186457516
commandserver: send pgid in hello message
Jun Wu <quark@fb.com>
parents:
29548
diff
changeset
|
352 hellomsg += '\n' |
ee8186457516
commandserver: send pgid in hello message
Jun Wu <quark@fb.com>
parents:
29548
diff
changeset
|
353 hellomsg += 'pgid: %d' % os.getpgid(0) |
14719
c19de7f32961
cmdserver: write the hello message as one chunk on the 'o' channel
Idan Kamara <idankk86@gmail.com>
parents:
14707
diff
changeset
|
354 |
c19de7f32961
cmdserver: write the hello message as one chunk on the 'o' channel
Idan Kamara <idankk86@gmail.com>
parents:
14707
diff
changeset
|
355 # 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
|
356 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
|
357 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
358 try: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
359 while self.serveone(): |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
360 pass |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
361 except EOFError: |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
362 # 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
|
363 # its request |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
364 return 1 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
365 |
2e9f379de0ac
serve: add --cmdserver option to communicate with hg over a pipe
Idan Kamara <idankk86@gmail.com>
parents:
diff
changeset
|
366 return 0 |
22988
32b77aba2772
cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents:
22563
diff
changeset
|
367 |
40842
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
368 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
|
369 """Set up server logging facility |
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
370 |
40842
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
371 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
|
372 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
|
373 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
|
374 """ |
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
375 # developer config: cmdserver.log |
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
376 logpath = ui.config(b'cmdserver', b'log') |
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
377 if not logpath: |
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
378 return |
40842
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
379 tracked = {b'cmdserver'} |
40841
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
380 |
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
381 global logfile |
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
382 if logpath == b'-': |
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
383 logfile = ui.ferr |
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
384 else: |
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
385 logfile = open(logpath, 'ab') |
368ecbf734af
commandserver: enable logging when server process started
Yuya Nishihara <yuya@tcha.org>
parents:
40838
diff
changeset
|
386 |
40842
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
387 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
|
388 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
|
389 elif logpath == b'-': |
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
390 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
|
391 else: |
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
392 logpath = os.path.abspath(logpath) |
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
393 vfs = vfsmod.vfs(os.path.dirname(logpath)) |
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
394 logger = loggingutil.filelogger(vfs, os.path.basename(logpath), tracked) |
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
395 |
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
396 targetuis = {ui} |
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
397 if repo: |
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
398 targetuis.add(repo.baseui) |
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
399 targetuis.add(repo.ui) |
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
400 for u in targetuis: |
82210d88d814
commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents:
40841
diff
changeset
|
401 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
|
402 |
22988
32b77aba2772
cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents:
22563
diff
changeset
|
403 class pipeservice(object): |
32b77aba2772
cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents:
22563
diff
changeset
|
404 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
|
405 self.ui = ui |
bc374458688b
cmdserver: postpone creation of pipe server until run()
Yuya Nishihara <yuya@tcha.org>
parents:
23322
diff
changeset
|
406 self.repo = repo |
22988
32b77aba2772
cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents:
22563
diff
changeset
|
407 |
32b77aba2772
cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents:
22563
diff
changeset
|
408 def init(self): |
32b77aba2772
cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents:
22563
diff
changeset
|
409 pass |
32b77aba2772
cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents:
22563
diff
changeset
|
410 |
32b77aba2772
cmdserver: wrap 'pipe' mode server by service object
Yuya Nishihara <yuya@tcha.org>
parents:
22563
diff
changeset
|
411 def run(self): |
23323
bc374458688b
cmdserver: postpone creation of pipe server until run()
Yuya Nishihara <yuya@tcha.org>
parents:
23322
diff
changeset
|
412 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
|
413 # 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
|
414 # hooks will never cause corruption of channel protocol. |
37127
6715e8035b4f
procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents:
37126
diff
changeset
|
415 with procutil.protectedstdio(ui.fin, ui.fout) as (fin, fout): |
40635
9683dfb6f13a
commandserver: fix reference before assignment error in pipeservice cleanup
Yuya Nishihara <yuya@tcha.org>
parents:
40361
diff
changeset
|
416 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
|
417 try: |
6715e8035b4f
procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents:
37126
diff
changeset
|
418 return sv.serve() |
6715e8035b4f
procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents:
37126
diff
changeset
|
419 finally: |
6715e8035b4f
procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents:
37126
diff
changeset
|
420 sv.cleanup() |
22989
dc8803ce3dfe
cmdserver: switch service objects by mode
Yuya Nishihara <yuya@tcha.org>
parents:
22988
diff
changeset
|
421 |
29586
42cdba9cfee4
commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents:
29585
diff
changeset
|
422 def _initworkerprocess(): |
29609
591c3badff2e
commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents:
29588
diff
changeset
|
423 # 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
|
424 # 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
|
425 # 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
|
426 # remains in a same session) |
591c3badff2e
commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents:
29588
diff
changeset
|
427 # 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
|
428 # 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
|
429 # cause trouble for things like ncurses. |
591c3badff2e
commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents:
29588
diff
changeset
|
430 # 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
|
431 # 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
|
432 # processes like ssh will be killed properly, without affecting |
591c3badff2e
commandserver: update comment about setpgid
Jun Wu <quark@fb.com>
parents:
29588
diff
changeset
|
433 # unrelated processes. |
29585
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
434 os.setpgid(0, 0) |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
435 # 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
|
436 # same state inherited from parent. |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
437 random.seed() |
29542
6011ad3b0a42
commandserver: manually create file objects from socket
Yuya Nishihara <yuya@tcha.org>
parents:
29532
diff
changeset
|
438 |
29586
42cdba9cfee4
commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents:
29585
diff
changeset
|
439 def _serverequest(ui, repo, conn, createcmdserver): |
40359
558114fa7bc1
py3: system-stringify file mode in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents:
40358
diff
changeset
|
440 fin = conn.makefile(r'rb') |
558114fa7bc1
py3: system-stringify file mode in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents:
40358
diff
changeset
|
441 fout = conn.makefile(r'wb') |
29585
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
442 sv = None |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
443 try: |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
444 sv = createcmdserver(repo, conn, fin, fout) |
22994
840be5ca03e1
cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents:
22990
diff
changeset
|
445 try: |
29585
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
446 sv.serve() |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
447 # 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
|
448 # known exceptions are caught by dispatch. |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
449 except error.Abort as inst: |
38809
afc4ad706f9c
dispatch: making all hg abortions be output with a specific label
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents:
38303
diff
changeset
|
450 ui.error(_('abort: %s\n') % inst) |
29585
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
451 except IOError as inst: |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
452 if inst.errno != errno.EPIPE: |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
453 raise |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
454 except KeyboardInterrupt: |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
455 pass |
29513
e5b4d79a9140
commandserver: backport handling of forking server from chgserver
Yuya Nishihara <yuya@tcha.org>
parents:
29512
diff
changeset
|
456 finally: |
29585
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
457 sv.cleanup() |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
458 except: # re-raises |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
459 # 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
|
460 # 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
|
461 if sv: |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
462 cerr = sv.cerr |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
463 else: |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
464 cerr = channeledoutput(fout, 'e') |
40361
b7de186efd82
py3: don't use traceback.print_exc() in commandserver.py
Yuya Nishihara <yuya@tcha.org>
parents:
40359
diff
changeset
|
465 cerr.write(encoding.strtolocal(traceback.format_exc())) |
29585
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
466 raise |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
467 finally: |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
468 fin.close() |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
469 try: |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
470 fout.close() # implicit flush() may cause another EPIPE |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
471 except IOError as inst: |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
472 if inst.errno != errno.EPIPE: |
6ed452d0f1f1
commandserver: unindent superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents:
29580
diff
changeset
|
473 raise |
22994
840be5ca03e1
cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents:
22990
diff
changeset
|
474 |
29544
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
475 class unixservicehandler(object): |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
476 """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
|
477 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
478 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
|
479 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
|
480 """ |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
481 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
482 pollinterval = None |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
483 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
484 def __init__(self, ui): |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
485 self.ui = ui |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
486 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
487 def bindsocket(self, sock, address): |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
488 util.bindunixsocket(sock, address) |
32276
c8b9943c07eb
commandserver: move "listen" responsibility from service to handler
Jun Wu <quark@fb.com>
parents:
30944
diff
changeset
|
489 sock.listen(socket.SOMAXCONN) |
32277
1ada3d18e7fb
commandserver: move printbanner logic to bindsocket
Jun Wu <quark@fb.com>
parents:
32276
diff
changeset
|
490 self.ui.status(_('listening at %s\n') % address) |
1ada3d18e7fb
commandserver: move printbanner logic to bindsocket
Jun Wu <quark@fb.com>
parents:
32276
diff
changeset
|
491 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
|
492 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
493 def unlinksocket(self, address): |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
494 os.unlink(address) |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
495 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
496 def shouldexit(self): |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
497 """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
|
498 return False |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
499 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
500 def newconnection(self): |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
501 """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
|
502 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
503 def createcmdserver(self, repo, conn, fin, fout): |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
504 """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
|
505 serves for the current connection""" |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
506 return server(self.ui, repo, fin, fout) |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
507 |
29548
9da1adc18639
commandserver: drop old unixservice implementation
Yuya Nishihara <yuya@tcha.org>
parents:
29544
diff
changeset
|
508 class unixforkingservice(object): |
22994
840be5ca03e1
cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents:
22990
diff
changeset
|
509 """ |
840be5ca03e1
cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents:
22990
diff
changeset
|
510 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
|
511 """ |
29548
9da1adc18639
commandserver: drop old unixservice implementation
Yuya Nishihara <yuya@tcha.org>
parents:
29544
diff
changeset
|
512 |
9da1adc18639
commandserver: drop old unixservice implementation
Yuya Nishihara <yuya@tcha.org>
parents:
29544
diff
changeset
|
513 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
|
514 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
|
515 self.repo = repo |
840be5ca03e1
cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents:
22990
diff
changeset
|
516 self.address = opts['address'] |
29548
9da1adc18639
commandserver: drop old unixservice implementation
Yuya Nishihara <yuya@tcha.org>
parents:
29544
diff
changeset
|
517 if not util.safehasattr(socket, 'AF_UNIX'): |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25832
diff
changeset
|
518 raise error.Abort(_('unsupported platform')) |
22994
840be5ca03e1
cmdserver: add service that listens on unix domain socket and forks process
Yuya Nishihara <yuya@tcha.org>
parents:
22990
diff
changeset
|
519 if not self.address: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25832
diff
changeset
|
520 raise error.Abort(_('no socket path specified with --address')) |
29544
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
521 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
|
522 self._sock = None |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
523 self._oldsigchldhandler = None |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
524 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
|
525 self._socketunlinked = None |
29544
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
526 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
527 def init(self): |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
528 self._sock = socket.socket(socket.AF_UNIX) |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
529 self._servicehandler.bindsocket(self._sock, self.address) |
37123
a8a902d7176e
procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
37122
diff
changeset
|
530 if util.safehasattr(procutil, 'unblocksignal'): |
a8a902d7176e
procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
37122
diff
changeset
|
531 procutil.unblocksignal(signal.SIGCHLD) |
29544
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
532 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
|
533 self._oldsigchldhandler = o |
30919
a95fc01aaffe
commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents:
30528
diff
changeset
|
534 self._socketunlinked = False |
a95fc01aaffe
commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents:
30528
diff
changeset
|
535 |
a95fc01aaffe
commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents:
30528
diff
changeset
|
536 def _unlinksocket(self): |
a95fc01aaffe
commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents:
30528
diff
changeset
|
537 if not self._socketunlinked: |
a95fc01aaffe
commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents:
30528
diff
changeset
|
538 self._servicehandler.unlinksocket(self.address) |
a95fc01aaffe
commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents:
30528
diff
changeset
|
539 self._socketunlinked = True |
29544
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
540 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
541 def _cleanup(self): |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
542 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
|
543 self._sock.close() |
30919
a95fc01aaffe
commandserver: prevent unlink socket twice
Jun Wu <quark@fb.com>
parents:
30528
diff
changeset
|
544 self._unlinksocket() |
29544
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
545 # 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
|
546 self._reapworkers(0) |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
547 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
548 def run(self): |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
549 try: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
550 self._mainloop() |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
551 finally: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
552 self._cleanup() |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
553 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
554 def _mainloop(self): |
30920
b1b36c6499c2
commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents:
30919
diff
changeset
|
555 exiting = False |
29544
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
556 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
|
557 selector = selectors.DefaultSelector() |
b0ffcb540357
commandserver: prefer first-party selectors module from Python 3 to backport
Augie Fackler <augie@google.com>
parents:
36843
diff
changeset
|
558 selector.register(self._sock, selectors.EVENT_READ) |
30920
b1b36c6499c2
commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents:
30919
diff
changeset
|
559 while True: |
b1b36c6499c2
commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents:
30919
diff
changeset
|
560 if not exiting and h.shouldexit(): |
b1b36c6499c2
commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents:
30919
diff
changeset
|
561 # 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
|
562 # we stop queuing new requests. |
b1b36c6499c2
commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents:
30919
diff
changeset
|
563 # 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
|
564 # accept()-ed), handle them before exit. otherwise, clients |
b1b36c6499c2
commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents:
30919
diff
changeset
|
565 # waiting for recv() will receive ECONNRESET. |
b1b36c6499c2
commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents:
30919
diff
changeset
|
566 self._unlinksocket() |
b1b36c6499c2
commandserver: handle backlog before exiting
Jun Wu <quark@fb.com>
parents:
30919
diff
changeset
|
567 exiting = True |
40450
41f0529b5112
commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents:
40361
diff
changeset
|
568 try: |
41f0529b5112
commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents:
40361
diff
changeset
|
569 ready = selector.select(timeout=h.pollinterval) |
41f0529b5112
commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents:
40361
diff
changeset
|
570 except OSError as inst: |
41f0529b5112
commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents:
40361
diff
changeset
|
571 # selectors2 raises ETIMEDOUT if timeout exceeded while |
41f0529b5112
commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents:
40361
diff
changeset
|
572 # handling signal interrupt. That's probably wrong, but |
41f0529b5112
commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents:
40361
diff
changeset
|
573 # we can easily get around it. |
41f0529b5112
commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents:
40361
diff
changeset
|
574 if inst.errno != errno.ETIMEDOUT: |
41f0529b5112
commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents:
40361
diff
changeset
|
575 raise |
41f0529b5112
commandserver: get around ETIMEDOUT raised by selectors2
Yuya Nishihara <yuya@tcha.org>
parents:
40361
diff
changeset
|
576 ready = [] |
33543
3ef3bf704e47
commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents:
33506
diff
changeset
|
577 if not ready: |
3ef3bf704e47
commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents:
33506
diff
changeset
|
578 # 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
|
579 if exiting: |
3ef3bf704e47
commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents:
33506
diff
changeset
|
580 break |
3ef3bf704e47
commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents:
33506
diff
changeset
|
581 continue |
29544
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
582 try: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
583 conn, _addr = self._sock.accept() |
33543
3ef3bf704e47
commandserver: do not handle EINTR for selector.select
Jun Wu <quark@fb.com>
parents:
33506
diff
changeset
|
584 except socket.error as inst: |
29544
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
585 if inst.args[0] == errno.EINTR: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
586 continue |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
587 raise |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
588 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
589 pid = os.fork() |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
590 if pid: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
591 try: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
592 self.ui.debug('forked worker process (pid=%d)\n' % pid) |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
593 self._workerpids.add(pid) |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
594 h.newconnection() |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
595 finally: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
596 conn.close() # release handle in parent process |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
597 else: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
598 try: |
38303
c07424ec633c
commandserver: close server's fds explicitly from a worker
Jun Wu <quark@fb.com>
parents:
38038
diff
changeset
|
599 selector.close() |
c07424ec633c
commandserver: close server's fds explicitly from a worker
Jun Wu <quark@fb.com>
parents:
38038
diff
changeset
|
600 self._sock.close() |
29587
536eec443b4a
commandserver: rename _serveworker() to _runworker()
Yuya Nishihara <yuya@tcha.org>
parents:
29586
diff
changeset
|
601 self._runworker(conn) |
29544
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
602 conn.close() |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
603 os._exit(0) |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
604 except: # never return, hence no re-raises |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
605 try: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
606 self.ui.traceback(force=True) |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
607 finally: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
608 os._exit(255) |
33506
8a1a7935c047
commandserver: close selector explicitly
Jun Wu <quark@fb.com>
parents:
33503
diff
changeset
|
609 selector.close() |
29544
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
610 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
611 def _sigchldhandler(self, signal, frame): |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
612 self._reapworkers(os.WNOHANG) |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
613 |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
614 def _reapworkers(self, options): |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
615 while self._workerpids: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
616 try: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
617 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
|
618 except OSError as inst: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
619 if inst.errno == errno.EINTR: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
620 continue |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
621 if inst.errno != errno.ECHILD: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
622 raise |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
623 # 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
|
624 self._workerpids.clear() |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
625 return |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
626 if pid == 0: |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
627 # no waitable child processes |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
628 return |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
629 self.ui.debug('worker process exited (pid=%d)\n' % pid) |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
630 self._workerpids.discard(pid) |
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
631 |
29587
536eec443b4a
commandserver: rename _serveworker() to _runworker()
Yuya Nishihara <yuya@tcha.org>
parents:
29586
diff
changeset
|
632 def _runworker(self, conn): |
29544
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
633 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
|
634 _initworkerprocess() |
29544
024e8f82f3de
commandserver: add new forking server implemented without using SocketServer
Yuya Nishihara <yuya@tcha.org>
parents:
29543
diff
changeset
|
635 h = self._servicehandler |
29586
42cdba9cfee4
commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents:
29585
diff
changeset
|
636 try: |
42cdba9cfee4
commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents:
29585
diff
changeset
|
637 _serverequest(self.ui, self.repo, conn, h.createcmdserver) |
42cdba9cfee4
commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents:
29585
diff
changeset
|
638 finally: |
42cdba9cfee4
commandserver: separate initialization and cleanup of forked process
Yuya Nishihara <yuya@tcha.org>
parents:
29585
diff
changeset
|
639 gc.collect() # trigger __del__ since worker process uses os._exit |