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