doc/docchecker
author Matt Harbison <matt_harbison@yahoo.com>
Tue, 21 Jan 2020 11:32:33 -0500
changeset 44273 43eea17ae7b3
parent 43691 47ef023d0165
child 45830 c102b704edb5
permissions -rwxr-xr-x
lfs: fix the stall and corruption issue when concurrently uploading blobs We've avoided the issue up to this point by gating worker usage with an experimental config. See 10e62d5efa73, and the thread linked there for some of the initial diagnosis, but essentially some data was being read from the blob before an error occurred and `keepalive` retried, but didn't rewind the file pointer. So the leading data was lost from the blob on the server, and the connection stalled, trying to send more data than available. In trying to recreate this, I was unable to do so uploading from Windows to CentOS 7. But it reproduced every time going from CentOS 7 to another CentOS 7 over https. I found recent fixes in the FaceBook repo to address this[1][2]. The commit message for the first is: The KeepAlive HTTP implementation is bugged in it's retry logic, it supports reading from a file pointer, but doesn't support rewinding of the seek cursor when it performs a retry. So it can happen that an upload fails for whatever reason and will then 'hang' on the retry event. The sequence of events that get triggered are: - Upload file A, goes OK. Keep-Alive caches connection. - Upload file B, fails due to (for example) failing Keep-Alive, but LFS file pointer has been consumed for the upload and fd has been closed. - Retry for file B starts, sets the Content-Length properly to the expected file size, but since file pointer has been consumed no data will be uploaded, causing the server to wait for the uploaded data until either client or server reaches a timeout, making it seem as our mercurial process hangs. This is just a stop-gap measure to prevent this behavior from blocking Mercurial (LFS has retry logic). A proper solutions need to be build on top of this stop-gap measure: for upload from file pointers, we should support fseek() on the interface. Since we expect to consume the whole file always anyways, this should be safe. This way we can seek back to the beginning on a retry. I ported those two patches, and it works. But I see that `url._sendfile()` does a rewind on `httpsendfile` objects[3], so maybe it's better to keep this all in one place and avoid a second seek. We may still want the first FaceBook patch as extra protection for this problem in general. The other two uses of `httpsendfile` are in the wire protocol to upload bundles, and to upload largefiles. Neither of these appear to use a worker, and I'm not sure why workers seem to trigger this, or if this could have happened without a worker. Since `httpsendfile` already has a `close()` method, that is dropped. That class also explicitly says there's no `__len__` attribute, so that is removed too. The override for `read()` is necessary to avoid the progressbar usage per file. [1] https://github.com/facebookexperimental/eden/commit/c350d6536d90c044c837abdd3675185644481469 [2] https://github.com/facebookexperimental/eden/commit/77f0d3fd0415e81b63e317e457af9c55c46103ee [3] https://www.mercurial-scm.org/repo/hg/file/5.2.2/mercurial/url.py#l176 Differential Revision: https://phab.mercurial-scm.org/D7962
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
27730
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
     1
#!/usr/bin/env python
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
     2
#
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
     3
# docchecker - look for problematic markup
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
     4
#
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
     5
# Copyright 2016 timeless <timeless@mozdev.org> and others
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
     6
#
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
     7
# This software may be used and distributed according to the terms of the
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
     8
# GNU General Public License version 2 or any later version.
29168
8f2805ce93d9 py3: make doc/docchecker use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28811
diff changeset
     9
29169
c9ab5a0bc7c5 py3: make doc/docchecker use print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29168
diff changeset
    10
from __future__ import absolute_import, print_function
29168
8f2805ce93d9 py3: make doc/docchecker use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28811
diff changeset
    11
41006
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    12
import os
29168
8f2805ce93d9 py3: make doc/docchecker use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28811
diff changeset
    13
import re
27730
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
    14
import sys
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
    15
41006
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    16
try:
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    17
    import msvcrt
43691
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    18
41006
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    19
    msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    20
    msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    21
except ImportError:
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    22
    pass
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    23
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    24
stdout = getattr(sys.stdout, 'buffer', sys.stdout)
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    25
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    26
leadingline = re.compile(br'(^\s*)(\S.*)$')
28810
9934362978e1 docchecker: report context line at most once
timeless <timeless@mozdev.org>
parents: 28049
diff changeset
    27
9934362978e1 docchecker: report context line at most once
timeless <timeless@mozdev.org>
parents: 28049
diff changeset
    28
checks = [
43691
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    29
    (
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    30
        br""":hg:`[^`]*'[^`]*`""",
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    31
        b"""warning: please avoid nesting ' in :hg:`...`""",
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    32
    ),
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    33
    (br'\w:hg:`', b'warning: please have a space before :hg:'),
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    34
    (
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    35
        br"""(?:[^a-z][^'.])hg ([^,;"`]*'(?!hg)){2}""",
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    36
        b'''warning: please use " instead of ' for hg ... "..."''',
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    37
    ),
28810
9934362978e1 docchecker: report context line at most once
timeless <timeless@mozdev.org>
parents: 28049
diff changeset
    38
]
27730
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
    39
43691
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    40
27730
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
    41
def check(line):
28810
9934362978e1 docchecker: report context line at most once
timeless <timeless@mozdev.org>
parents: 28049
diff changeset
    42
    messages = []
9934362978e1 docchecker: report context line at most once
timeless <timeless@mozdev.org>
parents: 28049
diff changeset
    43
    for match, msg in checks:
9934362978e1 docchecker: report context line at most once
timeless <timeless@mozdev.org>
parents: 28049
diff changeset
    44
        if re.search(match, line):
9934362978e1 docchecker: report context line at most once
timeless <timeless@mozdev.org>
parents: 28049
diff changeset
    45
            messages.append(msg)
9934362978e1 docchecker: report context line at most once
timeless <timeless@mozdev.org>
parents: 28049
diff changeset
    46
    if messages:
41006
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    47
        stdout.write(b'%s\n' % line)
28810
9934362978e1 docchecker: report context line at most once
timeless <timeless@mozdev.org>
parents: 28049
diff changeset
    48
        for msg in messages:
41006
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    49
            stdout.write(b'%s\n' % msg)
27730
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
    50
43691
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    51
27730
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
    52
def work(file):
41006
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    53
    (llead, lline) = (b'', b'')
27730
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
    54
28049
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    55
    for line in file:
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    56
        # this section unwraps lines
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    57
        match = leadingline.match(line)
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    58
        if not match:
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    59
            check(lline)
41006
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    60
            (llead, lline) = (b'', b'')
28049
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    61
            continue
27730
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
    62
28049
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    63
        lead, line = match.group(1), match.group(2)
43691
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    64
        if lead == llead:
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    65
            if lline != b'':
41006
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    66
                lline += b' ' + line
28049
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    67
            else:
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    68
                lline = line
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    69
        else:
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    70
            check(lline)
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    71
            (llead, lline) = (lead, line)
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    72
    check(lline)
27730
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
    73
43691
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    74
27730
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
    75
def main():
28049
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    76
    for f in sys.argv[1:]:
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    77
        try:
41006
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    78
            with open(f, 'rb') as file:
28049
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    79
                work(file)
c00f67c15c5a docchecker: use indentation of 4 spaces
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28048
diff changeset
    80
        except BaseException as e:
41006
9bfbb9fc5871 py3: byteify docchecker
Matt Harbison <matt_harbison@yahoo.com>
parents: 29169
diff changeset
    81
            sys.stdout.write(r"failed to process %s: %s\n" % (f, e))
27730
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
    82
43691
47ef023d0165 black: blacken scripts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41006
diff changeset
    83
27730
ed86fb2a4187 docchecker: introduce a way to check for poor markup
timeless <timeless@mozdev.org>
parents:
diff changeset
    84
main()