cmd/go/internal/lockedfile: clean *.lock files

juzqafwq  于 6个月前  发布在  Go
关注(0)|答案(3)|浏览(54)

你使用的Go版本是什么(go version)?

go version go1.12

$GOPATH/pkg/mod/cache/download/server.com/xxx/repo中,有必要清理这些*.lock文件吗?

这些文件的大小总是为0。也许我们可以在解锁后删除这些文件。
从代码注解中:

// We use a separate lockfile here instead of locking listFile itself because
// we want to use Rename to write the file atomically. The list may be read by
// a GOPROXY HTTP server, and if we crash midway through a rewrite (or if the
// HTTP server ignores our locking and serves the file midway through a
// rewrite) it's better to serve a stale list than a truncated one.

cc @bcmills

2vuwiymt

2vuwiymt1#

也许我们可以在解锁后删除这些文件。
版本特定的锁在两个地方使用:
go/src/cmd/go/internal/modfetch/fetch.go
第76行 42e8b9c
| | unlock, err:=lockVersion(mod) |
go/src/cmd/go/internal/modfetch/fetch.go
第158行 42e8b9c
| | unlock, err:=lockVersion(mod) |
由于它们保护了 .zip 文件和提取出的目录的创建,因此在文件和目录创建后可能可以删除这些锁文件。

xv8emn3q

xv8emn3q2#

删除锁文件是微妙的,这样很容易引入竞争条件。在POSIX系统中,我们使用建议锁,这不会阻止在锁定时由另一个进程更改或删除文件。考虑以下顺序:

  • 进程A锁定 list.lock 并开始更新 list 文件。
  • 进程B尝试锁定 list.lock ,但由于被A持有而阻塞。
  • 进程A完成 list 文件并解锁 list.lock
  • 进程B获取 list.lock
  • 进程A删除 list.lock
  • 进程C看到没有 list.lock 文件,创建一个并锁定它。

现在进程B和C都在更新 list 文件。
要解决这种情况,我们需要始终在解锁之前删除文件,并在锁定之后始终检查文件的身份。

  • 进程A锁定 list.lock 并开始更新 list 文件。
  • 进程B尝试锁定 list.lock ,但由于被A持有而阻塞。
  • 进程A完成 list 文件并解锁 list.lock
  • 进程A删除 list.lock (或重命名它)。
  • 进程A解锁已删除的 list.lock
  • 进程B获取已删除的 list.lock
  • 进程C看到没有 list.lock 文件,创建一个并锁定它。
  • 进程B检查它锁定的文件以确保该文件仍然是 list.lock ,发现它不是,并重新启动锁定过程。
  • 进程B尝试锁定新的 list.lock ,但由于被C持有而阻塞。

这需要更复杂的锁定顺序(B需要验证它锁定的文件的身份),我不确定这是否可移植(我不知道Windows是否允许锁定的文件被删除或重命名)。

相关问题