当并行调用多个实例时,xvfb-run不可靠

时间:2015-05-19 17:20:05

标签: xvfb

你能帮助我,为什么有时候会(50:50):

webkit_server.NoX11Error: Cannot connect to X. You can try running with xvfb-run.

当我以并行方式启动脚本时:

xvfb-run -a python script.py 

你可以这样自己重现:

for ((i=0; i<10; i++)); do
  xvfb-run -a xterm &
done

在这个启动的10个xterm实例中,其中9个通常会失败,退出并显示消息Xvfb failed to start

1 个答案:

答案 0 :(得分:28)

查看xvfb-run 1.0,其操作如下:

# Find a free server number by looking at .X*-lock files in /tmp.
find_free_servernum() {
    # Sadly, the "local" keyword is not POSIX.  Leave the next line commented in
    # the hope Debian Policy eventually changes to allow it in /bin/sh scripts
    # anyway.
    #local i

    i=$SERVERNUM
    while [ -f /tmp/.X$i-lock ]; do
        i=$(($i + 1))
    done
    echo $i
}

这是非常糟糕的做法:如果find_free_servernum的两个副本同时运行,则两者都不会知道另一个副本,因此他们都可以确定相同的号码可用,即使只有其中一个将能够使用它。

所以,要解决这个问题,让我们编写自己的代码来查找一个免费的显示编号,而不是假设xvfb-run -a可以正常工作:

#!/bin/bash

# allow settings to be updated via environment
: "${xvfb_lockdir:=$HOME/.xvfb-locks}"
: "${xvfb_display_min:=99}"
: "${xvfb_display_max:=599}"

# assuming only one user will use this, let's put the locks in our own home directory
# avoids vulnerability to symlink attacks.
mkdir -p -- "$xvfb_lockdir" || exit

i=$xvfb_display_min     # minimum display number
while (( i < xvfb_display_max )); do
  if [ -f "/tmp/.X$i-lock" ]; then                # still avoid an obvious open display
    (( ++i )); continue
  fi
  exec 5>"$xvfb_lockdir/$i" || continue           # open a lockfile
  if flock -x -n 5; then                          # try to lock it
    exec xvfb-run --server-num="$i" "$@" || exit  # if locked, run xvfb-run
  fi
  (( i++ ))
done

如果将此脚本保存为xvfb-run-safe,则可以调用:

xvfb-run-safe python script.py 

...只要您的系统上没有其他用户也在运行xvfb,就不用担心竞争条件。

可以这样测试:

for ((i=0; i<10; i++)); do xvfb-wrap-safe xchat & done

...在这种情况下,所有10个实例都正确启动并在后台运行,而不是:

for ((i=0; i<10; i++)); do xvfb-run -a xchat & done

...其中,根据您系统的时间安排,十分之九将(通常)失败。