你正在使用的Go版本是什么( go version
)?
$ go version
go version go1.15 linux/amd64
这个问题在最新版本的发布中是否重现?
还没有尝试,但看起来相关代码没有发生变化。
你正在使用什么操作系统和处理器架构( go env
)?
go env
输出
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/kyle/.cache/go-build"
GOENV="/home/kyle/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/kyle/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/kyle/"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/kyle/src/klarose/golang/net/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build211380463=/tmp/go-build -gno-record-gcc-switches"
你做了什么?
在使用x/net/webdav运行一个webdav服务器时,我发现任何试图重命名一个被锁定文件的操作都会失败,除非客户端对目标文件持有锁。这似乎是错误的。
复现步骤:
编译 https://github.com/hacdias/webdav (这个使用x/net/webdav作为其服务器)。
运行以下命令:
cd $(mktemp -d)
cat > config.yaml <<EOF
# Server related settings
address: 127.0.0.1
port: 8080
auth: false
tls: false
prefix: /
scope: .
modify: true
rules: []
EOF
webdav -p 8080 --auth=false
下载/构建/安装/等 cadaver (一个用于运行webdav命令的简单工具)
运行 cadaver http://localhost:8080
在其命令提示符下运行以下命令:
A
lock foo.yaml
mv foo.yaml foo.yaml.2
然后运行:
B
lock foo.yaml.2
mv foo.yaml foo.yaml.2
你期望看到什么?
A应该成功 -- foo.yaml
应该被重命名为 foo.yaml.2
:
dav:/> lock foo.yaml
Locking `foo.yaml': succeeded.
dav:/> mv foo.yaml foo.yaml.2
Moving `/foo.yaml' to `/foo.yaml.2': succeeded.
你看到了什么?
A失败了,但B成功了:
dav:/> lock foo.yaml
Locking `foo.yaml': succeeded.
dav:/> mv foo.yaml foo.yaml.2
Moving `/foo.yaml' to `/foo.yaml.2': failed:
412 Precondition Failed
dav:/> lock foo.yaml.2
Locking `foo.yaml.2': succeeded.
dav:/> mv foo.yaml foo.yaml.2
Moving `/foo.yaml' to `/foo.yaml.2': succeeded.
dav:/>
4条答案
按热度按时间pepwfjgg1#
一些后续思考/评论:
我的发现表明,您只能将源移动到锁定的目标,这是不正确的。锁定的资源应该简单地重命名,根据webdav RFC丢弃锁:
通过检查代码,看起来锁定子系统接受一个可选的src/dst参数。如果两者都设置了,它会尝试在两个资源上加锁。如果只设置了一个,它只会对那个资源加锁。如果两者都没有设置,它会暂时加锁以保持与其他客户端的锁定一致性。
在移动处理程序中,由于存在src和dst,它会在两个地方查找锁,即使dst不存在或未解锁:
因此,尽管我们只锁定了src,而dst不存在,请求仍会失败,因为我们没有在dst上获得有效的锁。
实际上,检查应该是“对于给定的资源,如果没有条件,就对其加临时锁”,而不是“如果没有条件,就对所有资源加临时锁”。
如果有兴趣,我可以研究实现修复这个问题的方法(以及 #42839 )。这两个问题目前都在阻碍我们,所以我们需要尽快找到解决方案(即接下来的几周)。我可以研究提交带有修复的PR。我不介意那些对这个代码库有经验的人提供一些指导,特别是针对这个问题,因为我认为修复可能不像 #42839 那么简单。
wdebmtf22#
/cc @bradfitz
cqoc49vn3#
我有一个潜在的解决方案。我会等待我的CLA通过,但欢迎大家随时查看。
ws51t4hk4#
https://golang.org/cl/285754提到了这个问题:
webdav: only require locks when necessary