2
2
require 'singleton'
3
3
require 'timeout'
4
4
5
+ DESIRED_DISPLAY = ":1.0" . freeze
6
+
5
7
module ArduinoCI
6
8
7
9
# When arduino commands run, they need a graphical display.
@@ -24,6 +26,41 @@ def existing_display?
24
26
false
25
27
end
26
28
29
+ # check whether a process is alive
30
+ # https://stackoverflow.com/a/32513298/2063546
31
+ def alive? ( pid )
32
+ Process . kill ( 0 , pid )
33
+ true
34
+ rescue
35
+ false
36
+ end
37
+
38
+ # check whether an X server is taking connections
39
+ def xserver_exist? ( display )
40
+ system ( { "DISPLAY" => display } , "xdpyinfo" , out : File ::NULL , err : File ::NULL )
41
+ end
42
+
43
+ # wait for the xvfb command to launch
44
+ # @param display [String] the value of the DISPLAY env var
45
+ # @param pid [Int] the process of Xvfb
46
+ # @param timeout [Int] the timeout in seconds
47
+ # @return [Bool] whether we detected a launch
48
+ def xvfb_launched? ( display , pid , timeout )
49
+ Timeout . timeout ( timeout ) do
50
+ loop do
51
+ unless alive? pid
52
+ puts "Xvfb process has died"
53
+ return false
54
+ end
55
+ x = xserver_exist? display
56
+ puts "xdpyinfo reports X server status as #{ x } "
57
+ return true if x
58
+ end
59
+ end
60
+ rescue Timeout ::Error
61
+ false
62
+ end
63
+
27
64
# enable a virtual display
28
65
def enable
29
66
if @existing
@@ -35,14 +72,18 @@ def enable
35
72
return unless @pid . nil? # TODO: disable first?
36
73
37
74
# open Xvfb
38
- xvfb_cmd = [ "Xvfb" , ":1" , "-ac" , "-screen" , "0" , "1280x1024x16" ]
75
+ xvfb_cmd = [
76
+ "Xvfb" ,
77
+ "+extension" , "RANDR" ,
78
+ ":1" ,
79
+ "-ac" ,
80
+ "-screen" , "0" ,
81
+ "1280x1024x16" ,
82
+ ]
39
83
puts "pipeline_start for Xvfb"
40
84
pipe = IO . popen ( xvfb_cmd )
41
85
@pid = pipe . pid
42
- sleep ( 3 ) # TODO: test a connection to the X server?
43
- @enabled = true
44
- puts "\n \n xdpyinfo:\n \n "
45
- system ( environment , "xdpyinfo" )
86
+ @enabled = xvfb_launched? ( DESIRED_DISPLAY , @pid , 30 )
46
87
end
47
88
48
89
# disable the virtual display
@@ -106,7 +147,7 @@ def run_silent(*args)
106
147
def environment
107
148
return nil unless @existing || @enabled
108
149
return { } if @existing
109
- { "DISPLAY" => ":1.0" }
150
+ { "DISPLAY" => DESIRED_DISPLAY }
110
151
end
111
152
112
153
# On finalize, ensure child process is ended
0 commit comments