4

I'm running the following pyqt application on an xvfb server on amazon ec2 ubuntu 12.04, I get the correct ouput from the qt application but I always get the aforementioned error when the app is done. Why am I getting this error? I think it may be because the xvfb server is not terminating correctly but I'm not sure.

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtWebKit import *
from xvfbwrapper import Xvfb


args = {"nolisten":"tcp"}
vdisplay = Xvfb(**args)
vdisplay.start()
app = QApplication(sys.argv)
def update():
    print "upd"
t = QTimer()
t.start(500)
t.timeout.connect(update)
stopTimer = QTimer(timeout=app.quit,singleShot=True)
stopTimer.start(4000)
app.exec_()
print "done with app"
vdisplay.stop()
Archetype2
  • 97
  • 1
  • 10

3 Answers3

3

For me @urim's solution does not work because if you don't use vdisplay.stop(), the Xvfb process is not killed when the script exits, which is a problem. My solution is to explicitly kill the process with a background call, after a short while:

# Workaround for a problem preventing vdisplay.stop() to work
# normally, because apparently Qt is still keeping its handle on X
# at this point.
import os
os.system('(sleep 5 && kill -9 %d) &' % vdisplay.proc.pid)
cjauvin
  • 3,433
  • 4
  • 29
  • 38
  • Sleeping for a short time after termination also resolves similar error messages when running directly using xvfb-run (although I copied and modified xvfb-run to do so) – Gnat Apr 26 '16 at 07:10
1

Another ugly way to work around this is to wrap everything in another subprocess:

import xvfbwrapper
import sys
import subprocess as sub

with xvfbwrapper.Xvfb():
    p = sub.Popen(
        ["python", "yourscript.py"] + sys.argv[1:],
        stdout=sub.PIPE, stderr=sub.PIPE
    )
    stdout, stderr = p.communicate()
    print stdout
    print >> sys.stderr, stderr
    sys.exit(p.returncode)
mpenkov
  • 21,621
  • 10
  • 84
  • 126
1

You get the error as long as the QApplication instance is alive. One solution is to push the Xvfb.stop() call closer to the exit of the program, for instance with the atexit module:

import atexit

# ...

def main():
    vdisplay = Xvfb()
    vdisplay.start()
    atexit.register(vdisplay.stop)

    # ...
BlackJack
  • 4,476
  • 1
  • 20
  • 25