@@ -61,6 +61,17 @@ def _lock_files():
61
61
ls = [p for p in ls if os .path .isfile (p )]
62
62
return ls
63
63
64
+ def _unlock_display (ndisplay ):
65
+ lockf = os .path .join ('/tmp' , '.X%d-lock' % ndisplay )
66
+ try :
67
+ os .remove (lockf )
68
+ except :
69
+ return False
70
+
71
+ return True
72
+
73
+
74
+
64
75
def _search_for_free_display ():
65
76
ls = [int (x .split ('X' )[1 ].split ('-' )[0 ]) for x in _lock_files ()]
66
77
min_display_num = 1000
@@ -946,6 +957,36 @@ def _check_version_requirements(self, trait_object, raise_exception=True):
946
957
version , max_ver ))
947
958
return unavailable_traits
948
959
960
+ def _run_wrapper (self , runtime ):
961
+ sysdisplay = os .getenv ('DISPLAY' )
962
+ if self ._redirect_x :
963
+ try :
964
+ from xvfbwrapper import Xvfb
965
+ except ImportError :
966
+ iflogger .error ('Xvfb wrapper could not be imported' )
967
+ raise
968
+
969
+ vdisp = Xvfb (nolisten = 'tcp' )
970
+ vdisp .start ()
971
+ vdisp_num = vdisp .vdisplay_num
972
+
973
+ iflogger .info ('Redirecting X to :%d' % vdisp_num )
974
+ runtime .environ ['DISPLAY' ] = ':%d' % vdisp_num
975
+
976
+ runtime = self ._run_interface (runtime )
977
+
978
+ if self ._redirect_x :
979
+ if sysdisplay is None :
980
+ os .unsetenv ('DISPLAY' )
981
+ else :
982
+ os .environ ['DISPLAY' ] = sysdisplay
983
+
984
+ iflogger .info ('Freeing X :%d' % vdisp_num )
985
+ vdisp .stop ()
986
+ _unlock_display (vdisp_num )
987
+
988
+ return runtime
989
+
949
990
def _run_interface (self , runtime ):
950
991
""" Core function that executes interface
951
992
"""
@@ -982,14 +1023,7 @@ def run(self, **inputs):
982
1023
hostname = getfqdn (),
983
1024
version = self .version )
984
1025
try :
985
- if self ._redirect_x :
986
- from xvfbwrapper import Xvfb
987
- with Xvfb () as xvfb :
988
- runtime = self ._run_interface (runtime )
989
- else :
990
- iflogger .warn ('Error redirecting X, trying without xvfb...' )
991
- runtime = self ._run_interface (runtime )
992
-
1026
+ runtime = self ._run_wrapper (runtime )
993
1027
outputs = self .aggregate_outputs (runtime )
994
1028
runtime .endTime = dt .isoformat (dt .utcnow ())
995
1029
timediff = parseutc (runtime .endTime ) - parseutc (runtime .startTime )
@@ -1097,6 +1131,25 @@ def version(self):
1097
1131
self .__class__ .__name__ )
1098
1132
return self ._version
1099
1133
1134
+ def _exists_in_path (self , cmd , environ ):
1135
+ '''
1136
+ Based on a code snippet from
1137
+ http://orip.org/2009/08/python-checking-if-executable-exists-in.html
1138
+ '''
1139
+
1140
+ if 'PATH' in environ :
1141
+ input_environ = environ .get ("PATH" )
1142
+ else :
1143
+ input_environ = os .environ .get ("PATH" , "" )
1144
+ extensions = os .environ .get ("PATHEXT" , "" ).split (os .pathsep )
1145
+ for directory in input_environ .split (os .pathsep ):
1146
+ base = os .path .join (directory , cmd )
1147
+ options = [base ] + [(base + ext ) for ext in extensions ]
1148
+ for filename in options :
1149
+ if os .path .exists (filename ):
1150
+ return True , filename
1151
+ return False , None
1152
+
1100
1153
1101
1154
class Stream (object ):
1102
1155
"""Function to capture stdout and stderr streams with timestamps
@@ -1149,32 +1202,39 @@ def _read(self, drain):
1149
1202
self ._lastidx = len (self ._rows )
1150
1203
1151
1204
1152
- def run_command (runtime , output = None , timeout = 0.01 ):
1205
+ def run_command (runtime , output = None , timeout = 0.01 , redirect_x = False ):
1153
1206
"""Run a command, read stdout and stderr, prefix with timestamp.
1154
1207
1155
1208
The returned runtime contains a merged stdout+stderr log with timestamps
1156
1209
"""
1157
1210
PIPE = subprocess .PIPE
1158
1211
1212
+ cmdline = runtime .cmdline
1213
+ if redirect_x :
1214
+ exist_xvfb , _ = self ._exists_in_path ('xvfb-run' , runtime .environ )
1215
+ if not exist_val :
1216
+ raise RuntimeError ('Xvfb was not found, X redirection aborted' )
1217
+ cmdline = 'xvfb-run -a ' + cmdline
1218
+
1159
1219
if output == 'file' :
1160
1220
errfile = os .path .join (runtime .cwd , 'stderr.nipype' )
1161
1221
outfile = os .path .join (runtime .cwd , 'stdout.nipype' )
1162
1222
stderr = open (errfile , 'wt' )
1163
1223
stdout = open (outfile , 'wt' )
1164
1224
1165
- proc = subprocess .Popen (runtime . cmdline ,
1225
+ proc = subprocess .Popen (cmdline ,
1166
1226
stdout = stdout ,
1167
1227
stderr = stderr ,
1168
1228
shell = True ,
1169
1229
cwd = runtime .cwd ,
1170
1230
env = runtime .environ )
1171
1231
else :
1172
- proc = subprocess .Popen (runtime . cmdline ,
1173
- stdout = PIPE ,
1174
- stderr = PIPE ,
1175
- shell = True ,
1176
- cwd = runtime .cwd ,
1177
- env = runtime .environ )
1232
+ proc = subprocess .Popen (cmdline ,
1233
+ stdout = PIPE ,
1234
+ stderr = PIPE ,
1235
+ shell = True ,
1236
+ cwd = runtime .cwd ,
1237
+ env = runtime .environ )
1178
1238
result = {}
1179
1239
errfile = os .path .join (runtime .cwd , 'stderr.nipype' )
1180
1240
outfile = os .path .join (runtime .cwd , 'stdout.nipype' )
@@ -1405,6 +1465,10 @@ def version_from_command(self, flag='-v'):
1405
1465
o , e = proc .communicate ()
1406
1466
return o
1407
1467
1468
+ def _run_wrapper (self , runtime ):
1469
+ runtime = self ._run_interface (runtime )
1470
+ return runtime
1471
+
1408
1472
def _run_interface (self , runtime , correct_return_codes = [0 ]):
1409
1473
"""Execute command via subprocess
1410
1474
@@ -1432,32 +1496,14 @@ def _run_interface(self, runtime, correct_return_codes=[0]):
1432
1496
setattr (runtime , 'command_path' , cmd_path )
1433
1497
setattr (runtime , 'dependencies' , get_dependencies (executable_name ,
1434
1498
runtime .environ ))
1435
- runtime = run_command (runtime , output = self .inputs .terminal_output )
1499
+ runtime = run_command (runtime , output = self .inputs .terminal_output ,
1500
+ redirect_x = self ._redirect_x )
1436
1501
if runtime .returncode is None or \
1437
1502
runtime .returncode not in correct_return_codes :
1438
1503
self .raise_exception (runtime )
1439
1504
1440
1505
return runtime
1441
1506
1442
- def _exists_in_path (self , cmd , environ ):
1443
- '''
1444
- Based on a code snippet from
1445
- http://orip.org/2009/08/python-checking-if-executable-exists-in.html
1446
- '''
1447
-
1448
- if 'PATH' in environ :
1449
- input_environ = environ .get ("PATH" )
1450
- else :
1451
- input_environ = os .environ .get ("PATH" , "" )
1452
- extensions = os .environ .get ("PATHEXT" , "" ).split (os .pathsep )
1453
- for directory in input_environ .split (os .pathsep ):
1454
- base = os .path .join (directory , cmd )
1455
- options = [base ] + [(base + ext ) for ext in extensions ]
1456
- for filename in options :
1457
- if os .path .exists (filename ):
1458
- return True , filename
1459
- return False , None
1460
-
1461
1507
def _format_arg (self , name , trait_spec , value ):
1462
1508
"""A helper function for _parse_inputs
1463
1509
0 commit comments