Jenkins + Play 1.2.4:cobertura 锁定文件的问题/报告

Posted

技术标签:

【中文标题】Jenkins + Play 1.2.4:cobertura 锁定文件的问题/报告【英文标题】:Jenkins + Play 1.2.4 : problems with cobertura lock files / report 【发布时间】:2012-09-22 04:56:22 【问题描述】:

我们有一个 Play 1.2.4 应用程序,并且我们为该应用程序安装了 Jenkins(在 Ubuntu 上)。我们遇到了 Cobertura 的问题。

运行测试(成功)后,我们时不时地收到以下错误:

---------------------------------------
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at net.sourceforge.cobertura.util.FileLocker.lock(FileLocker.java:124)
        at play.modules.cobertura.CoberturaPlugin$CoberturaPluginShutdownThread.run(Unknown Source)
Caused by: java.nio.channels.OverlappingFileLockException
        at sun.nio.ch.FileChannelImpl$SharedFileLockTable.checkList(FileChannelImpl.java:1166)
        at sun.nio.ch.FileChannelImpl$SharedFileLockTable.add(FileChannelImpl.java:1068)
        at sun.nio.ch.FileChannelImpl.lock(FileChannelImpl.java:824)
        at java.nio.channels.FileChannel.lock(FileChannel.java:860)
        ... 6 more
---------------------------------------
Unable to get lock on /var/lib/jenkins/jobs/project/workspace/cobertura.ser.lock: null
This is known to happen on Linux kernel 2.6.20.
Make sure cobertura.jar is in the root classpath of the jvm 
process running the instrumented code.  If the instrumented code 
is running in a web server, this means cobertura.jar should be in 
the web server's lib directory.
Don't put multiple copies of cobertura.jar in different WEB-INF/lib directories.
Only one classloader should load cobertura.  It should be the root classloader.
---------------------------------------
lock file could not be deleted

这似乎并没有“破坏构建”,但进一步向下构建,我们得到以下(导致 cobertura 报告失败)

Publishing Cobertura coverage report...
No coverage results were found using the pattern 'test-result/code-coverage/coverage.xml' relative to '/var/lib/jenkins/jobs/project/workspace'.  Did you enter a pattern relative to the correct directory?  Did you generate the XML report(s) for Cobertura?
Build step 'Publish Cobertura Coverage Report' changed build result to FAILURE

手动运行后续构建通常会通过。

根据Zero code coverage with cobertura 1.9.2 but tests are working,我尝试在播放自动测试命令后设置-Dcobertura.use.java.nio=false

由于这个错误只是偶尔发生,我不确定这是否有帮助。但在那之后,我们遇到了播放自动测试挂起的问题:

  ...
  Executing /opt/play-1.2.4/play auto-test "/var/lib/jenkins/jobs/project/workspace"  -Dcobertura.use.java.nio=false
  [workspace] $ /opt/play-1.2.4/play auto-test "/var/lib/jenkins/jobs/project/workspace" -Dcobertura.use.java.nio=false
  <build stuck here for a couple of days>

由于没有什么东西是完全确定的,所以在这里很难说因果关系。 (这似乎发生在 jenkins/server 重启后的一两次构建之后)

目前我正在考虑在我们的项目中禁用 Cobertura,但如果有人有其他想法,那就太好了 =)

【问题讨论】:

我们遇到了完全相同的问题!我也以同样的方式尝试了 cobertura.use.java.nio,它也挂起...... @valanto : 你有什么环境? 和我想的一样。在 Ubuntu 机器上运行 jenkins。使用 play1.2.4,cobertura 模块 2.4,最新的 jenkins。我们也在 jenkins 上运行自动测试,当我尝试 -Dcobertura.use.java.nio=false 时它也挂了。我们在 cobertura 上的失败也时断时续…… 我设法通过添加一个虚拟机作为 Jenkins 的奴隶来克服这个问题。 Master 正在运行 Ubuntu 并且没有获得任何构建作业,slave 正在运行 Centos 并且尚未显示错误(大约 300 个构建)。我不知道是什么开始导致错误,我偶尔会在我的 Win7 工作站上得到它(给出关于 Linux 内核的相同消息:P) @LeonidasK :所以 Centos 似乎没有 Ubuntu 出现的这个问题(至少到目前为止) 【参考方案1】:

很明显,这是由于您的 JVM 实现中的 JVM 锁定问题,或者更确切地说,是您部署 cobertura JAR 的方式。

Jenkins 可以生成大量 JVM 线程,如果 cobetura 在您的全局类路径中,则可能会发生一些奇怪的冲突。

我认为,最终,这应该归因于 cobertura 中的一个小错误(除非复杂的 corbertura 文件锁定正在解决一些其他更重要的问题)。

根据 Cobertura 的 FileLock 的源代码 (cobertura/src/main/java/net/sourceforge/cobertura/util/FileLocker.java),多个 JVM 加载 Cobertura jar 存在一些问题。

要解决此问题,请确保只有一个副本和一个应用程序启动和使用 Corbetura。

您的 VM 实现修复它的原因很可能是您减少了加载 cobetrura 方式的可变性。另外,也许您正在以比您的詹金斯服务器更高的频率重新启动您的虚拟机。

在我们的 jenkins corbertura 构建中,我们只使用了 maven 插件,这似乎可以正常工作而没有问题(但话又说回来,我们没有使用 java 1.7,也没有使用 Play)。

【讨论】:

【参考方案2】:

这一直困扰着我们一段时间(玩 1.2.4/Jenkins)。由于 jenkins cobertura 插件(报告发布)和播放框架 cobertura 模块之间的序列重叠,存在一些问题。我相信这纯粹是时间巧合,因此是断断续续的。由于缺乏更好的解决方案,我们进行了以下工作。

从主要构建作业中删除了 jenkins cobertura 报告发布操作。我们创建了一个新的 jenkins 作业,该作业设置为发布 cobertura 覆盖率报告操作。在新作业中,我们使用 shell 操作将 coverage.xml 从主构建作业工作区复制到新作业的工作区,以便运行 cobertura 覆盖率报告发布操作。复制(出于显而易见的原因)是为了避免在同一个工作中同时运行 play cobertura 和 jenkins cobertura。

这不是最好的,但很高兴看到覆盖率报告/图表 :-)

【讨论】:

【参考方案3】:

诀窍是每个模块使用一个数据文件 (cobertura.ser) 以避免并行任务的锁定。

用蚂蚁:

<cobertura-instrument todir="$build.dir" datafile="cobertura.ser.$modulename">
    ...

最后将多个 cobertura 文件合并为一个 cobertura 文件:

<target name="merge-coverage">
    <cobertura-merge datafile="cobertura.ser">
        <fileset dir="$build.dir">
            <include name="cobertura.ser.*" />
        </fileset>
    </cobertura-merge>
</target>

【讨论】:

【参考方案4】:

-Dcobertura.use.java.nio=false 前一个似乎需要更改为 true 才能使用文件锁定,如您的错误消息所述。

此外,应用程序可能需要在某处添加 cobertura 的完整文件夹类路径。

它appears 你正在使用类似于 COF(constantly open file) 的东西,错误消息是指一个存在的文件,但是 文件的区域 被锁定在驱动器中,不仅仅是文件本身。

【讨论】:

【参考方案5】:

你设置了吗

%test.play.tmp=none

在您的 application.conf 文件中?

【讨论】:

这应该是一个答案,而不是一个问题。

以上是关于Jenkins + Play 1.2.4:cobertura 锁定文件的问题/报告的主要内容,如果未能解决你的问题,请参考以下文章

如何部署和运行 Play! 2.1 通过 Jenkins 到 EC2

如何使用 Jenkins 在本地自动部署 Play Framework (2.4) 应用程序?

Play- 1.2.4 xss 自动转义问题

在 Play 1.2.4 中运行测试套件

从play框架1.2.4远程访问mysql数据库

如何使用 Play 1.2.4 指定 Ehcache 设置