Fix multiple cleanup bug caused by threading
Use a lock to guarantee that cleanup is called only once per test
diff --git a/TestON/core/teston.py b/TestON/core/teston.py
index 271c0dd..657e659 100644
--- a/TestON/core/teston.py
+++ b/TestON/core/teston.py
@@ -32,7 +32,7 @@
import new
import xmldict
import importlib
-import os
+import threading
module = new.module("test")
import openspeak
global path, drivers_path, core_path, tests_path,logs_path
@@ -91,6 +91,8 @@
self.logs_path = logs_path
self.driver = ''
self.Thread = Thread
+ self.cleanupFlag = False
+ self.cleanupLock = threading.Lock()
self.configparser()
verifyOptions(options)
@@ -290,7 +292,7 @@
else:
self.stepCache += "No Result\n"
self.stepResults.append(self.STEPRESULT)
- except StandardError as e:
+ except StandardError:
self.log.exception( "\nException in the following section of" +
" code: " + str(testCaseNumber) + "." +
str(step) + ": " + self.stepName )
@@ -343,33 +345,51 @@
def cleanup(self):
'''
- Release all the component handles and the close opened file handles.
- This will return TRUE if all the component handles and log handles closed properly,
- else return FALSE
+ Print a summary of the current test's results then attempt to release
+ all the component handles and the close opened file handles.
+ This function shouldbe threadsafe such that cleanup will only be
+ executed once per test.
+
+ This will return TRUE if all the component handles and log handles
+ closed properly, else return FALSE.
'''
result = self.TRUE
- self.logger.testSummary(self)
-
- #self.reportFile.close()
-
- #utilities.send_mail()
- for component in self.componentDictionary.keys():
- try :
- tempObject = vars(self)[component]
- print "Disconnecting from " + str(tempObject.name) + ": " + \
- str(tempObject)
- tempObject.disconnect()
- #tempObject.execute(cmd="exit",prompt="(.*)",timeout=120)
-
- except (Exception):
- self.log.exception( "Exception while disconnecting from " +
- str( component ) )
- result = self.FALSE
- # Closing all the driver's session files
- for driver in self.componentDictionary.keys():
- vars(self)[driver].close_log_handles()
-
+ lock = self.cleanupLock
+ if lock.acquire( False ):
+ try:
+ if self.cleanupFlag is False: # First thread to run this
+ self.cleanupFlag = True
+ self.logger.testSummary(self)
+ for component in self.componentDictionary.keys():
+ try :
+ tempObject = vars(self)[component]
+ print "Disconnecting from " + str(tempObject.name) + ": " + \
+ str(tempObject)
+ tempObject.disconnect()
+ except Exception:
+ self.log.exception( "Exception while disconnecting from " +
+ str( component ) )
+ result = self.FALSE
+ # Closing all the driver's session files
+ for driver in self.componentDictionary.keys():
+ try:
+ vars(self)[driver].close_log_handles()
+ except Exception:
+ self.log.exception( "Exception while closing log files for " +
+ str( driver ) )
+ result = self.FALSE
+ else:
+ pass # Someone else already ran through this function
+ finally:
+ lock.release()
+ else: # Someone already has a lock
+ # NOTE: This could cause problems if we don't release the lock
+ # correctly
+ lock.acquire() # Wait for the other thread to finish
+ # NOTE: If we don't wait, exit could be called while the thread
+ # with the lock is still cleaning up
+ lock.release()
return result
def pause(self):
@@ -577,6 +597,12 @@
def exit(self):
__builtin__.testthread = None
+ for thread in threading.enumerate():
+ if thread.isAlive():
+ try:
+ thread._Thread__stop()
+ except:
+ print(str(thread.getName()) + ' could not be terminated' )
sys.exit()
def verifyOptions(options):
@@ -606,7 +632,7 @@
main.classPath = "examples."+main.TEST+"."+main.TEST
else :
print "Test or Example not specified please specify the --test <test name > or --example <example name>"
- self.exit()
+ main.exit()
def verifyExample(options):
if options.example:
@@ -798,21 +824,5 @@
print sys.exc_info()[1]
main.exit()
-def load_defaultlogger():
- '''
- It will load the default parser which is xml parser to parse the params and topology file.
- '''
- moduleList = main.loggerPath.split("/")
- newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
- try :
- loggerClass = main.loggerClass
- loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
- loggerClass = getattr(loggerModule, loggerClass)
- main.logger = loggerClass()
-
- except ImportError:
- print sys.exc_info()[1]
- main.exit()
-
def _echo(self):
print "THIS IS ECHO"