守卫使fsnotify虚假地检测文件更改

时间:2019-09-19 07:53:18

标签: linux watchman

我正在为Git的core.fsmonitor设置使用值班员。我正在运行使用fsnotify来检测文件更改和运行内部版本的其他工具。监视人员正在执行的操作是使fsnotify认为文件在不更改时就在更改(fsnotify工具正在不断运行构建版本)。我如何才能发现正在发生的事情,以便使该工具能够忽略这些更改?

3 个答案:

答案 0 :(得分:1)

每次执行看门人查询时,都要进行查询同步;为了确保从内核更改通知队列中读取了查询开始之前的所有文件更改,这是必需的。

Watchman将使用一个随机名称编写一个cookie文件,并等待在内核通知流中观察该文件以执行该同步。

此页面上有关同步的更多详细信息:https://facebook.github.io/watchman/docs/cookies.html

在我看来,集成中的fsnotify组件将受益于添加简单的过滤器;例如,在启动构建之前,仅匹配扩展名看起来似乎合理的源文件的文件。

答案 1 :(得分:0)

fsmonitor的守望者集成是淫荡,经修正后更加保守,版本为Git 2.25(2020年第一季度)。

这可能会对您的情况有所帮助。

请参见commit dd0b61fKevin Willford (kewillford)(2019年11月4日)。
(由Junio C Hamano -- gitster --commit fc7b26c中合并,2019年12月1日)

  

fsmonitor:修复了守望者集成

     

帮助:Derrick Stolee
  签名人:凯文·威尔福德

     

当快速运行Git命令(例如在Shell脚本或测试套件中)时,Git命令经常完成并在同一秒内重新启动。

     

示例fsmonitor的钩子可以与Watchman集成,从而将纳秒级的时间缩短为几秒钟。原则上,这很好,例如Watchman claims to use inclusive comparisons。结果只能是自上一个Git命令以来更改路径的过度表示。

     

但是,Watchman's own documentation声称“在了解文件树的完整状态时,使用时间戳容易导致争用情况”。
  他们所有已记录的示例都使用类似于“ clockspec”的“ c:123:234”。
  Git最终应该学习如何存储这种类型的字符串以提供更强大的集成,但这将是更具侵入性的更改。

     

使用GIT_TEST_FSMONITOR="$(pwd)/t7519/fsmonitor-watchman“时,由于这些竞争条件,诸如t7519-wtstatus.sh之类的脚本会失败。
  实际上,在GIT_TEST_FSMONITOR指向t/t7519/fsmonitor-wathcman的情况下运行任何测试脚本都会导致test_commit函数失败。
  由于创建git add "$indir$file"和'$file'命令之间没有足够的时间,因此'git add'命令失败。

     

现在,从传递给守望者的时间戳中减去一秒钟。
  这将使我们的窗口足够大,可以避免出现这些竞争情况。增大窗口会导致诸如t7519-wtstatus.sh之类的测试通过。

     

def437671中引入集成时(“ fsmonitor:为Watchman添加示例集成脚本”,2018-09-22,Git v2.16.0-rc0-mergebatch #5中列出),该查询包含一个表达式,该表达式将忽略在该窗口中创建和删除的文件。
  进行此更改的性能原因是忽略由Git命令之间的构建创建的临时文件。
  但是,这会在Git快速创建或删除文件的脚本场景中导致失败。

     

像以前一样使用GIT_TEST_FSMONITOR时,t2203-add-intent.sh由于这种添加和删除竞争条件而失败。

     

通过从Watchman查询中删除“表达式”,我们可以删除此竞争条件。如果用户在Git命令之间的工作目录内创建和删除临时文件,这将导致性能下降。但是,这是我们必须支付的正确费用。

答案 2 :(得分:0)

fsmonitor mentioned here 基于名为 Simple-IPCInter-process communication

Git 2.32(2021 年第 2 季度)详细介绍了它的介绍,然后将用于在顶部构建 fsmonitor 之类的服务。

参见 commit 36a7eb6commit 7cd5dbc(2021 年 3 月 22 日)和 commit 9fd1902commit 77e522ccommit 55144cccommit 4f98ce5、{{3} }、commit 59c7b88commit 066d523(2021 年 3 月 15 日),作者:commit 7455e05
请参阅 Jeff Hostetler (Jeff-Hostetler)commit 8c2efa5commit c4ba579commit 3a63c6a(2021 年 3 月 15 日)。
(由 Johannes Schindelin (dscho)Junio C Hamano -- gitster -- 合并,2021 年 4 月 2 日)

<块引用>

commit 861794b:添加 Unix 域套接字实现

签字人:Jeff Hostetler

<块引用>

创建基于 Unix 域套接字的“simple-ipc”实现。

一组 ipc_client 例程实现了一个客户端库,以通过 Unix 域套接字连接到 ipc_server,发送一个简单的请求,并接收一个响应。
客户端在套接字上使用阻塞 IO。

一组 ipc_server 例程实现了一个线程池来监听和并发服务客户端连接。

服务器在已知位置创建一个新的 Unix 域套接字。
如果已存在具有该名称的套接字,则服务器会尝试确定另一台服务器是否已在侦听该套接字或该套接字是否已失效。
如果套接字繁忙,服务器会以错误退出而不是窃取套接字。
如果套接字已死,服务器会创建一个新套接字并启动。

如果在运行时,服务器检测到它的套接字被另一个服务器窃取,它会自动退出。

<块引用>

simple-ipc:新 IPC 机制的设计文档

签字人:约翰内斯·辛德林
签字人:Jeff Hostetler

<块引用>

新 IPC 机制的简要设计文档,允许前台 Git 客户端使用命名管道或 unix 域套接字与已知位置的现有守护进程对话。

technical/api-simple-ipc 现在包含在其 simple-ipc 中:

<块引用>

简单的 IPC API

Simple-IPC API 是一组带有 ipc_ 前缀的库例程 以及允许 IPC 客户端进程的基本通信协议 将特定于应用程序的 IPC 请求消息发送到 IPC 服务器 处理并接收特定于应用程序的 IPC 响应消息。

通信发生在 Windows 和 Unix 域上的命名管道上 其他平台上的套接字。

IPC 客户端和 IPC 服务器在 先前商定的特定于应用程序的路径名(在 此设计的范围)是计算机系统本地的。

服务器应用程序进程中的 IPC 服务器例程创建一个 线程池监听连接并接收请求消息 来自多个并发 IPC 客户端。
收到这些消息后 被分派到服务器应用程序回调进行处理。 IPC 服务器例程然后增量地将响应中继回 IPC-客户端。

客户端应用程序进程中的 IPC 客户端例程连接 到 IPC 服务器并发送请求消息并等待响应。 收到后,将响应返回给调用方。

例如,fsmonitor--daemon 功能将构建为服务器 应用程序在 IPC 服务器库例程之上。它将有 线程监视文件系统事件和线程池等待 客户端连接。
客户端,例如 git status 将请求一个列表 自某个时间点以来的文件系统事件,服务器将 响应更改的文件和目录列表。
的格式 请求和响应是特定于应用程序的; IPC 客户端和 IPC 服务器例程将它们视为不透明的字节流。

与子流程模型对比

Simple-IPC 机制不同于现有的 sub-process.c 模型(文档/技术/长时间运行过程协议.txt)和 由 Git-LFS 等应用程序使用。在 LFS 风格的子流程模型中 helper 由前台进程启动,通信发生 通过一对绑定到标准输入/标准输出的文件描述符 子进程,子进程只为当前前台服务 进程,子进程在前台进程时退出 终止。

在 Simple-IPC 模型中,服务器是一个运行时间非常长的服务。它 可以同时为多个客户端提供服务并拥有一个私有套接字或 到每个活动客户端的命名管道连接。可能会启动 (按需)由当前的客户端进程或者它可能已经 由以前的客户端或操作系统在启动时启动。服务器 进程不与终端关联,它在之后仍然存在 客户终止。客户端无权访问标准输入/标准输出 服务器进程,因此必须通过套接字或 命名管道。

服务器启动和关闭

基于IPC-server的应用服务器是如何启动的 超出 Simple-IPC 设计的范围,是 应用程序使用它。例如,服务器可能已启动或 在日常维护操作期间重新启动,或者它可能 在系统启动序列期间作为系统服务启动,或者 可能会在需要时由前台 Git 命令按需启动。

同样,服务器关闭是应用程序的一个属性,使用 simple-ipc 例程。例如,服务器可能决定 空闲时或仅在明确请求时关闭。

简单的IPC协议

Simple-IPC 协议由来自 客户端和来自服务器的可选响应消息。这俩 客户端和服务器消息的长度没有限制并被终止 带有冲洗包。

pkt-line 例程 (Documentation/technical/protocol-common.txt) 用于在消息生成期间简化缓冲区管理, 传输和接收。一个flush包用来标记结束 的消息。这允许发送方逐步生成和 传递消息。它允许接收器增量接收 以块为单位的消息,并知道他们何时收到了整个消息 留言。

客户端请求和服务器响应的实际字节格式 消息是特定于应用程序的。 IPC 层传输和 将它们作为不透明的字节缓冲区接收,而无需担心 内的内容。调用应用层的工作是 了解请求和响应消息的内容。

总结

从概念上讲,Simple-IPC 协议类似于 HTTP REST 要求。客户端连接,使特定于应用程序和 无状态请求,接收特定于应用程序的请求 响应,并断开连接。这是一个往返设施 查询服务器。 Simple-IPC 例程隐藏套接字, 命名管道和线程池详细信息并允许应用程序 层专注于手头的应用程序。


警告:在没有 pthreads 支持的情况下,“simple-ipc”无法编译,但构建过程没有正确解释:这已在 Git 2.32(2021 年第二季度)中修复。

参见man pagecommit 6aac70a(2021 年 5 月 20 日)。
(2021 年 5 月 22 日在 Jeff Hostetler (Jeff-Hostetler)Junio C Hamano -- gitster -- 合并)

<块引用>

commit 6aae0e2:在定义 NO_PTHREADS 时更正 ifdefs

报告人:Randall S. Becker
帮助:Jeff King
签字人:Jeff Hostetler

<块引用>

简单的 IPC 总是需要线程(除了各种特定于平台的 IPC 支持)。
修复 ifdefs 中的 Makefile 以在适当时定义 SUPPORTS_SIMPLE_IPC

以前,代码的 Unix 版本只会验证 Unix 域套接字是否可用。

这个问题simple-ipc