Jenkins + Play 1.2.4: Cobertura锁文件/报告问题

62
我们有一个Play 1.2.4应用程序,并且我们为该应用程序在Ubuntu上安装了Jenkins。我们在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,我尝试在play auto-test命令之后设置-Dcobertura.use.java.nio=false

由于这个错误只是偶尔发生,我不确定这是否有所帮助。但是此后,我们遇到了play auto-test挂起的问题:

  ...
  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/服务器重新启动后的一两个构建之后)

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


2
我们有完全相同的问题!我也尝试了相同的方式使用cobertura.use.java.nio,但它也会卡住... - valanto
我想你的设置和我一样。在Ubuntu机器上运行Jenkins。使用play1.2.4,cobertura模块2.4和最新的Jenkins。我们还在Jenkins上运行play自动测试,当我尝试使用-Dcobertura.use.java.nio=false时,它也挂起了。我们与cobertura的失败也时好时坏... - valanto
3
我通过将虚拟机添加为Jenkins的从节点来解决了这个问题。主节点运行Ubuntu,不参与构建任务;从节点运行Centos,并且在约300次构建中尚未出现错误。我不知道是什么引起了这个错误,但偶尔会在我的Win7工作站上出现(并显示有关Linux内核的相同消息:P)。 - Leonidas K
@LeonidasK:所以Centos似乎没有Ubuntu出现的这个问题(至少目前为止)。 - Touko
尝试调整权限。我曾经遇到过一个类似的问题,与文件的权限有关。在构建脚本中的一个命令中,Jenkins无法读/写文件,但在另一个命令中可以。最终我们在机器上运行了 chmod 777 -R ~jenkins 命令,哈哈。 - reagan
显示剩余3条评论
5个回答

2

技巧在于每个模块使用一个数据文件(cobertura.ser)以避免并行任务中的锁。

使用ant:

<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>

2
这个问题困扰我们已经有一段时间了(play 1.2.4/Jenkins)。由于 Jenkins Cobertura 插件(报告发布)和 Play Framework Cobertura 模块之间的重叠序列存在问题,我认为这纯粹是时间巧合,因此是间歇性的。针对缺乏更好解决方法的情况,我们有以下解决方法。
我们从主要构建作业中删除了 Jenkins Cobertura 报告发布操作。我们创建了一个新的 Jenkins 作业,并设定了发布 Cobertura 覆盖范围报告操作。在新作业中,我们使用 shell 操作将 coverage.xml 从主要构建作业工作区复制到新作业的工作区,以便运行 Cobertura 覆盖范围报告发布操作。出于明显原因,复制操作是为了避免在同一个作业中同时运行 Play Cobertura 和 Jenkins Cobertura。
虽然并不是最佳方案,但能够看到覆盖范围报告/图表,我们感到非常高兴 :-)

2
显然,这是由于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服务器更频繁地重新启动VM。在我们的jenkins corbertura构建中,我们只使用maven插件,这似乎没有任何问题(但是,我们不使用java 1.7,也不使用Play)。

1
-Dcobertura.use.java.nio=false 看起来需要更改为true才能使用文件锁定,就像您的错误消息所解释的那样。
此外,应用程序可能需要添加完整的cobertura文件夹类路径。
似乎您正在使用类似于COF(不断打开文件)的东西,错误消息指的是存在的文件,但驱动器上的文件区域被锁定,而不仅仅是文件本身。

0
你设置了吗?
%test.play.tmp=none

在你的 application.conf 文件中?


2
这应该被表述为一个答案,而不是一个问题。 - jayunit100

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接