# Buggy code
def readGlobalFile(self, fileStoreID, userPath=None):
    """
    Returns an absolute path to a local, temporary copy of the file
    keyed by fileStoreID.

    *The returned file will be read only (have permissions 444).*

    :param userPath: a path to the name of file to which the global file will be
    copied or hard-linked (see below). userPath must either be: (1) a
    file path contained within a directory or, recursively, a subdirectory
    of a temporary directory returned by Job.FileStore.getLocalTempDir(),
    or (2) a file path returned by Job.FileStore.getLocalTempFile().
    If userPath is specified and this is not true a RuntimeError exception
    will be raised. If userPath is specified and the file is already cached,
    the userPath file will be a hard link to the actual location, else it
    will be an actual copy of the file.
    """
    if fileStoreID in self.filesToDelete:
        raise RuntimeError(
            "Trying to access a file in the jobStore you've deleted: %s" % fileStoreID
        )
    if userPath != None:
        userPath = os.path.abspath(userPath)  # Make an absolute path
        # Check it is a valid location
        if not userPath.startswith(self.localTempDir):
            raise RuntimeError(
                "The user path is not contained within the"
                " temporary file hierarchy created by the job."
                " User path: %s, temporary file root path: %s"
                % (userPath, self.localTempDir)
            )
    # When requesting a new file from the jobStore first check if fileStoreID
    # is a key in jobStoreFileIDToCacheLocation.
    if fileStoreID in self.jobStoreFileIDToCacheLocation:
        cachedAbsFilePath = self.jobStoreFileIDToCacheLocation[fileStoreID]
        # If the user specifies a location and it is not the current location
        # return a hardlink to the location, else return the original location
        if userPath == None or userPath == cachedAbsFilePath:
            return cachedAbsFilePath
        if os.path.exists(userPath):
            os.remove(userPath)
        os.link(cachedAbsFilePath, userPath)
        return userPath
    else:
        # If it is not in the cache read it from the jobStore to the
        # desired location
        localFilePath = userPath if userPath != None else self.getLocalTempFile()
        self.jobStore.readFile(fileStoreID, localFilePath)
        self.jobStoreFileIDToCacheLocation[fileStoreID] = localFilePath
        # Chmod to make file read only
        os.chmod(localFilePath, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
        return localFilePath


# Traceback (RuntimeError)
[centos@arjun-fake-podk toil_tests]$ python module_tests.py
No handlers could be found for logger "toil.resource"
INFO:toil.lib.bioio:Logging set at level: DEBUG
INFO:toil.lib.bioio:Logging to file: /data1/star_log
INFO:toil.common:Using the single machine batch system
INFO:toil.jobStores.fileJobStore:Jobstore directory is: /data1/toil_tempdir
WARNING:toil.batchSystems.singleMachine:Limiting maxCores to CPU count of system (8).
INFO:toil.batchSystems.singleMachine:Setting up the thread pool with 80 workers, given a minimum CPU fraction of 0.100000 and a maximum CPU value of 8.
INFO:toil.common:Written the environment for the jobs to the environment file
WARNING:toil.resource:Can't globalize module ModuleDescriptor(dirPath='/usr/local/lib/python2.7/site-packages', name='toil.job', extension='.pyc').
WARNING:toil.resource:Can't globalize module ModuleDescriptor(dirPath='/usr/local/lib/python2.7/site-packages', name='toil.job', extension='.pyc').
WARNING:toil.resource:Can't globalize module ModuleDescriptor(dirPath='/usr/local/lib/python2.7/site-packages', name='toil.job', extension='.pyc').
INFO:toil.leader:Checked batch system has no running jobs and no updated jobs
INFO:toil.leader:Found 1 jobs to start and 0 jobs with successors to run
INFO:toil.leader:Starting the main loop
DEBUG:toil.leader:Built the jobs list, currently have 1 jobs to update and 0 jobs issued
DEBUG:toil.batchSystems.singleMachine:Issuing the command: /usr/local/bin/python -E /usr/local/lib/python2.7/site-packages/toil/worker.py /data1/toil_tempdir e/j/jobaSjV4A with memory: 2147483648, cores: 1, disk: 2147483648
DEBUG:toil.leader:Issued job with job store ID: e/j/jobaSjV4A and job batch system ID: 0 and cores: 1, disk: 2147483648, and memory: 2147483648
DEBUG:toil.batchSystems.singleMachine:Acquiring 2147483648 bytes of memory from a pool of 9223372036854775807.
DEBUG:toil.batchSystems.singleMachine:Acquiring 10 fractional cores from a pool of 80 to satisfy a request of 1.000000 cores
INFO:toil.batchSystems.singleMachine:Executing command: '/usr/local/bin/python -E /usr/local/lib/python2.7/site-packages/toil/worker.py /data1/toil_tempdir e/j/jobaSjV4A'.
Exception in thread Thread-13:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/local/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/local/lib/python2.7/site-packages/toil/job.py", line 398, in asyncWrite
raise RuntimeError("The termination flag is set, exiting")
RuntimeError: The termination flag is set, exiting

Exception in thread Thread-14:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/local/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/local/lib/python2.7/site-packages/toil/job.py", line 398, in asyncWrite
raise RuntimeError("The termination flag is set, exiting")
RuntimeError: The termination flag is set, exiting

Exception RuntimeError: RuntimeError('cannot join current thread',) in <bound method FileStore.__del__ of <toil.job.FileStore object at 0x7f5142899f90>> ignored

# Fixed code
def readGlobalFile(self, fileStoreID, userPath=None, cache=True):
    """
    Returns an absolute path to a local, temporary copy of the file
    keyed by fileStoreID.

    :param userPath: a path to the name of file to which the global file will be
    copied or hard-linked (see below).

    :param cache: a boolean to switch on caching (see below). Caching will
    attempt to keep copies of files between sequences of jobs run on the same
    worker.

    If cache=True and userPath is either:
    (1) a file path contained within a directory or,
    recursively, a subdirectory of a temporary directory returned by
    Job.FileStore.getLocalTempDir(), or (2) a file path returned by
    Job.FileStore.getLocalTempFile() then the file will be cached and
    returned file will be read only (have permissions 444).
    If userPath is specified and the file is already cached,
    the userPath file will be a hard link to the actual location, else it
    will be an actual copy of the file.

    If the cache=False or userPath is not either of the above the file
    will not be cached and will have default permissions. Note, if the file
    is already cached this will result in two copies of the file on the system.

    :rtype : the absolute path to the read file
    """
    if fileStoreID in self.filesToDelete:
        raise RuntimeError(
            "Trying to access a file in the jobStore you've deleted: %s" % fileStoreID
        )
    if userPath != None:
        userPath = os.path.abspath(userPath)  # Make an absolute path
        # Turn off caching if user file is not in localTempDir
        if cache and not userPath.startswith(self.localTempDir):
            cache = False
    # When requesting a new file from the jobStore first check if fileStoreID
    # is a key in jobStoreFileIDToCacheLocation.
    if fileStoreID in self.jobStoreFileIDToCacheLocation:
        cachedAbsFilePath = self.jobStoreFileIDToCacheLocation[fileStoreID]
        if cache:
            # If the user specifies a location and it is not the current location
            # return a hardlink to the location, else return the original location
            if userPath == None or userPath == cachedAbsFilePath:
                return cachedAbsFilePath
            # Chmod to make file read only
            if os.path.exists(userPath):
                os.remove(userPath)
            os.link(cachedAbsFilePath, userPath)
            return userPath
        else:
            # If caching is not true then make a copy of the file
            localFilePath = userPath if userPath != None else self.getLocalTempFile()
            shutil.copyfile(cachedAbsFilePath, localFilePath)
            return localFilePath
    else:
        # If it is not in the cache read it from the jobStore to the
        # desired location
        localFilePath = userPath if userPath != None else self.getLocalTempFile()
        self.jobStore.readFile(fileStoreID, localFilePath)
        # If caching is enabled and the file is in local temp dir then
        # add to cache and make read only
        if cache:
            assert localFilePath.startswith(self.localTempDir)
            self.jobStoreFileIDToCacheLocation[fileStoreID] = localFilePath
            os.chmod(localFilePath, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
        return localFilePath