Commit Graph

29 Commits

Author SHA1 Message Date
Adam Simpkins
2a0b8f58fb update chg to correctly honor the pager.stderr setting
Summary:
Update the chg code to correctly honor the `pager.stderr` setting, and avoid
piping stderr to the pager when it is disabled.

Since only the server-side code knows the hg config values, the server-side
chgserver.py code passes this config setting back to the client when sending
the pager request.

Reviewed By: quark-zju

Differential Revision: D17109106

fbshipit-source-id: 6b69b1a7de9f61db51af7b0ba00d65fa5053a795
2019-09-09 11:48:42 -07:00
Adam Simpkins
e79dc29f0f refactor the chg code that sends system and pager requests
Summary:
This refactors the code the code that sends system and pager requests from the
chg server to the client.

Previously these were both sent using the `S` channel code.  The `S` channel
code was slightly unusual and had special handling: in general the code
assumed that upper-case channel codes did not include any request body data,
but this wasn't true for the `S` channel data.  I changed this to lower-case
in order to eliminate this special case handling, and I also split up the
system and pager data into different channel codes, since they have fairly
different behavior.  System requests are now sent with an `s` channel code,
and pager requests are sent with a `p` channel code.

I also changed the code to require that the server always adds a terminating
`\0` byte after each environment variable value.  Previously the client code
was responsible for adding a nul terminator on the last string, which could
potentially require the client to copy the data into a larger buffer in order
to do so.

I also made a minor change to the client-side `readchannel()` code so that it
can read the channel type and body data length with a single system call
instead of making 2 separate `recv()` calls.

The main benefit of these changes is that they will let the server pass some
additional configuration information with pager requests.  The change to make
use of this new field will come in a subsequent diff.

Reviewed By: quark-zju

Differential Revision: D17216291

fbshipit-source-id: c3044cf3d5f5e103f0b62d083e4ef3764160f20e
2019-09-09 11:48:42 -07:00
Jun Wu
74d5e02eb8 chg: remove hashstate and validation logic
Summary:
After D7840236 stack, it's possible to have a single chg server that handles
different [extensions] configurations. The 'validate' step and 'hashstate' were
mainly designed to detect changes of [extensions], the source code of the
extensions. That becomes unnecessary with the latest design.

Remove them to simplify the logic.

chg no longer creates symlink `server2 -> server2-hash`. Bump the name
to `server3` to explicitly break compatibility.

Reviewed By: xavierd

Differential Revision: D16866463

fbshipit-source-id: 5e1d00e6f895d9b8ead0bcabefcea11756f57c94
2019-08-28 19:26:26 -07:00
Jun Wu
5d9fba271f chg: restart server automatically if handshake takes too long
Summary:
Usually the handshake process is pretty quick (<0.01 seconds):

  chg: debug: 0.000148 try connect to ...
  chg: debug: 0.000338 connected to server
  chg: debug: 0.000359 initialize context buffer with size 4096
  chg: debug: 0.008225 hello received: ...
  chg: debug: 0.008269 capflags=0x7b03, pid=31941
  chg: debug: 0.008282 request setprocname, block size 17
  chg: debug: 0.008316 request attachio
  chg: debug: 0.008978 response read from channel r, size 4
  chg: debug: 0.009045 request chdir, block size 45
  chg: debug: 0.009092 version matched (6119653365548183087)

However, we have seen some OSX cases where the handshake and basically
everything takes much longer:

  chg: debug: 0.000139 try connect to ...
  chg: debug: 0.000297 connected to server
  chg: debug: 0.000321 initialize context buffer with size 4096
  chg: debug: 0.192316 hello received: ...
  chg: debug: 0.192362 capflags=0x7b03, pid=55634
  chg: debug: 0.192373 request setprocname, block size 17
  chg: debug: 0.192420 request attachio
  chg: debug: 0.229009 response read from channel r, size 4
  chg: debug: 0.229072 request chdir, block size 34
  chg: debug: 0.229111 version matched (6119653365548183087)

(See P59677258 for the full paste)

If restart the chg server, the problem goes away and commands will be fast
again.

Unfortunately I'm not sure about the root cause of the problem. Maybe it's
Python's GC doing something very expensive? Maybe it's OSX thinking the server
process is "inactive" and put it to some state that's very slow to recover? Or maybe
it's some weird 3rdparty service?

For now, what we do know are:
- The slowness *sometimes* reproduces with chg.
- The slowness goes away if chg server is restarted.

As a last resort, detect the slowness by measuring the handshake time, then
restart the server accordingly. To avoid an infinite restart loop on slow machines,
the restart can only happen once.

The threshold is set to 0.05 seconds, which is roughly 5x the normal value, and
can be disabled by `CHGSTARTTIMECHECK=0`.

Reviewed By: phillco

Differential Revision: D8294468

fbshipit-source-id: 75246ea4d872045664e7feadb0acc47dfa1d8eae
2018-06-05 22:02:50 -07:00
Wez Furlong
31bcfbe58e hg: disable check-code tests for C code
Summary:
They're actively fighting against the clang-format config
and don't have an auto-fix.

Reviewed By: quark-zju

Differential Revision: D8283622

fbshipit-source-id: 2de45f50e6370a5ed14915c6ff23dc843ff14e8a
2018-06-05 19:21:43 -07:00
Jun Wu
a6fcceea31 chg: make sure client and server have a matched version
Summary:
Generate a `u64` integer about the "version" at build time, and make chg
client check the version before connecting to the server.

This would ensure a chg client would only connect to a matched version of
the server.

- In setup.py, compute the "versionhash", write it as
  `mercurial.__version__.versionhash`.
- In dispatch.py, `mercurial.__version__` needs to be explicitly loaded
  before forking.
- In commandserver.py, send the versionhash to the client with the "hello"
  message.
- In chg.c, verify the versionhash. If it does not match, unlink the socket
  path and reconnect.

Reviewed By: farnz

Differential Revision: D7978131

fbshipit-source-id: 50acc923e72e40a4f66a96f01a194cf1a57fe832
2018-05-24 09:12:00 -07:00
Jun Wu
79e07a5585 chg: prefix (re|m)allocx with chg_
Summary:
This solves issues when the binary is linked with another C library that define
those functions.

Reviewed By: DurhamG

Differential Revision: D6888242

fbshipit-source-id: d714c7eb18bc4c281912df50567e7f176d64a669
2018-04-13 21:51:03 -07:00
Jun Wu
488ba17f87 chg: respect environment variables for pager
Previously chg runs the pager command without respecting its environment
variables being told to use. This patch makes it so.
2017-04-12 16:50:23 -07:00
Jun Wu
402691b892 chg: check snprintf result strictly
This makes the program more robust when somebody changes hgclient's
maxdatasize in the future.
2017-01-11 23:39:24 +08:00
Jun Wu
bb277b3ff3 chg: change server's process title
This patch uses the newly introduced "setprocname" interface to update the
process title server-side, to make it easier to tell what a worker is actually
doing.

The new title is "chg[worker/$PID]", where PID is the process ID of the
connected client. It can be directly observed using "ps -AF" under Linux, or
"ps -A" under FreeBSD.
2017-01-11 07:40:52 +08:00
Jun Wu
b61b02a865 chg: remove getpager support
We have enough bits to switch to the new chg pager code path in runcommand.
So just remove the legacy getpager support.

This is a red-only patch, and will break chg's pager support temporarily.
2017-01-10 06:59:39 +08:00
Jun Wu
5ae59a4110 chg: handle pager request client-side
This patch implements the simple S-channel pager handling at chg
client-side.

Note: It does not deal with environ and cwd currently for simplicity, which
will be fixed later.
2017-01-10 06:59:03 +08:00
Jun Wu
923ee6957d chg: check type read from S channel
The previous patch added the check server-side. This patch added it
client-side.
2017-01-06 16:14:52 +00:00
Jun Wu
734e02b02d chg: send type information via S channel (BC)
Previously S channel is only used to send system commands. It will also be
used to send pager commands. So add a type parameter.

This breaks older chg clients. But chg and hg should always come from a
single commit and be packed into a single package. Supporting running
inconsistent versions of chg and hg seems to be unnecessarily complicated
with little benefit. So just make the change and assume people won't use
inconsistent chg with hg.
2017-01-06 16:11:03 +00:00
Jun Wu
f437cb2c85 chg: handle connect failure before errno gets overridden
This patch moves the error handling logic up so that errno after connect
won't be overridden.
2016-12-25 23:32:11 +00:00
Jun Wu
8499ade54b chg: let hgc_open support long path
"sizeof(sun_path)" is too small. Use the chdir trick to support long socket
path, like "mercurial.util.bindunixsocket".

It's useful for cases where TMPDIR is long. Modern OS X rewrites TMPDIR to a
long value. And we probably want to use XDG_RUNTIME_DIR [2] for Linux.

The approach is a bit different from the previous plan, where we will have
hgc_openat and pass cmdserveropts.sockdirfd to it. That's because the
current change is easier: chg has to pass a full path to "hg" as the
"--address" parameter. There is no "--address-basename" or "--address-dirfd"
flags. The next patch will remove "sockdirfd".

Note: It'd be nice if we can use a native "connectat" implementation.
However, that's not available everywhere. Some platform (namely FreeBSD)
does support it, but the implementation has bugs so it cannot be used [2].

[1]: https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
[2]: https://www.mercurial-scm.org/pipermail/mercurial-devel/2016-April/082892.html
2016-12-23 16:37:00 +00:00
Yuya Nishihara
6c0a0f348a chg: just take it as EOF if recv() returns 0
hgc->sockfd is a blocking stream socket. recv() should never return 0 other
than EOF.

See 4ff8628991ea for the original problem.
2016-08-05 21:21:33 +09:00
Jun Wu
ecf32d3bf2 chg: handle EOF reading data block
We recently discovered a case in production that chg uses 100% CPU and is
trying to read data forever:

  recvfrom(4, "", 1814012019, 0, NULL, NULL) = 0

Using gdb, apparently readchannel() got wrong data. It was reading in an
infinite loop because rsize == 0 does not exit the loop, while the server
process had ended.

  (gdb) bt
  #0 ... in recv () at /lib64/libc.so.6
  #1 ... in readchannel (...) at /usr/include/bits/socket2.h:45
  #2 ... in readchannel (hgc=...) at hgclient.c:129
  #3 ... in handleresponse (hgc=...) at hgclient.c:255
  #4 ... in hgc_runcommand (hgc=..., args=<optimized>, argsize=<optimized>)
  #5 ... in main (argc=...486922636, argv=..., envp=...) at chg.c:661
  (gdb) frame 2
  (gdb) p *hgc
  $1 = {sockfd = 4, pid = 381152, ctx = {ch = 108 'l',
        data = 0x7fb05164f010 "st):\nTraceback (most recent call last):\n"
        "Traceback (most recent call last):\ne", maxdatasize = 1814065152,"
        " datasize = 1814064225}, capflags = 16131}

This patch addresses the infinite loop issue by detecting continuously empty
responses and abort in that case.

Note that datasize can be translated to ['l', ' ', 'l', 'a']. Concatenate
datasize and data, it forms part of "Traceback (most recent call last):".

This may indicate a server-side channeledoutput issue. If it is a race
condition, we may want to use flock to protect the channels.
2016-07-18 18:55:06 +01:00
Jun Wu
2106a129bc chg: add pgid to hgclient struct
The previous patch makes the server tell the client its pgid. This patch
stores it in hgclient_t and adds a function to get it.
2016-07-17 23:05:59 +01:00
Jun Wu
f8e2eeaa6b chg: extract the logic of setting FD_CLOEXEC to a utility function
Setting FD_CLOEXEC is useful for other fds such like lockfd and sockdirfd,
move the logic from hgc_open to util.
2016-04-11 00:17:17 +01:00
Jun Wu
7aec0cb63d chg: replace abortmsg showing errno with abortmsgerrno
Since we have abortmsgerrno now, use it to show human friendly error messages
across platforms.
2016-04-05 15:16:01 +01:00
Jun Wu
9c2bea1fcf chg: make connect debug message less repetitive
Before this patch, "connect to" debug message is printed repeatedly because
a previous patch changed how the chg client decides the server is ready to be
connected.

This patch revises the places we print connect debug messages so they are less
repetitive without losing useful information.
2016-04-04 02:36:05 +01:00
Jun Wu
f94ba7eabd chg: downgrade "failed to read channel" from abortmsg to debugmsg
If the server has an uncaught exception, it will exit without being able to
write the channel information. In this case, the client is likely to complain
about "failed to read channel", which looks inconsistent with original hg.
This patch silences the error message and makes uncaught exception behavior
more like original hg. It will help chg to pass test-fileset.t.
2016-03-14 23:28:14 +00:00
Jun Wu
80fd75af3b chgserver: add an explicit "reconnect" instruction to validate
In some rare cases (next patch), we may want validate to do "unlink" without
forcing the client reconnect. This patch addes a new "reconnect" instruction
and makes "unlink" not to reconnect by default.
2016-03-14 13:48:33 +00:00
Yuya Nishihara
f65fcd1944 chg: provide early exception to user
See the previous patch for details. Since the socket will be closed by the
server, handleresponse() will never return:

  Traceback (most recent call last):
    ...
  chg: abort: failed to read channel
2016-03-12 22:17:30 +09:00
Jun Wu
4d98436906 chg: implement validate in hgclient
This patch implements the corresponding validate method in hgclient.
It will return instruction strings as is without taking any real action.
2016-03-06 14:21:52 +00:00
Jun Wu
b5898933a2 chg: use mallocx and reallocx in hgclient
This patch simplifies the code a bit, and reduces the binary size a little.
2016-02-17 15:08:09 +00:00
Jun Wu
4da8e59d38 chg: forward umask from client to server
This is necessary to make chg test pass on test-inherit-mode.t.
2016-02-15 14:35:26 +00:00
Yuya Nishihara
58036583d5 chg: import frontend sources
These files are copied from
https://bitbucket.org/yuja/chg/ -r f897faa79687
2016-01-03 12:39:27 +09:00