# Buggy code
def fetch_and_execute_function_to_run(key, worker=global_worker):
    """Run on arbitrary function on the worker."""
    driver_id, serialized_function = worker.redis_client.hmget(
        key, ["driver_id", "function"]
    )
    try:
        # Deserialize the function.
        function = pickle.loads(serialized_function)
        # Run the function.
        function({"worker": worker})
    except Exception:
        # If an exception was thrown when the function was run, we record the
        # traceback and notify the scheduler of the failure.
        traceback_str = traceback.format_exc()
        # Log the error message.
        name = (
            function.__name__
            if ("function" in locals() and hasattr(function, "__name__"))
            else ""
        )
        ray.utils.push_error_to_driver(
            worker.redis_client,
            "function_to_run",
            traceback_str,
            driver_id=driver_id,
            data={"name": name},
        )


# Traceback (Exception)
Traceback (most recent call last):
File "/home/ubuntu/ray/python/ray/worker.py", line 1625, in fetch_and_execute_function_to_run
function = pickle.loads(serialized_function)
File "/home/ubuntu/ray/python/ray/tune/__init__.py", line 6, in <module>
from ray.tune.tune import run_experiments
File "/home/ubuntu/ray/python/ray/tune/tune.py", line 88, in <module>
from ray.rllib.shard.shardedagent import ShardedAgent
File "/home/ubuntu/ray/python/ray/rllib/__init__.py", line 18, in <module>
_register_all()
File "/home/ubuntu/ray/python/ray/rllib/__init__.py", line 13, in _register_all
register_trainable(key, get_agent_class(key))
File "/home/ubuntu/ray/python/ray/rllib/agent.py", line 368, in get_agent_class
from ray.rllib import es
File "/home/ubuntu/ray/python/ray/rllib/es/__init__.py", line 1, in <module>
from ray.rllib.es.es import (ESAgent, DEFAULT_CONFIG)
File "/home/ubuntu/ray/python/ray/rllib/es/es.py", line 43, in <module>
@ray.remote
File "/home/ubuntu/ray/python/ray/worker.py", line 2579, in remote
max_calls, checkpoint_interval)(args[0])
File "/home/ubuntu/ray/python/ray/worker.py", line 2482, in remote_decorator
function_properties)
File "/home/ubuntu/ray/python/ray/worker.py", line 2541, in remote_function_decorator
func_invoker, function_properties)
File "/home/ubuntu/ray/python/ray/worker.py", line 2380, in export_remote_function
check_main_thread()
File "/home/ubuntu/ray/python/ray/worker.py", line 959, in check_main_thread
.format(threading.current_thread().getName()))
Exception: The Ray methods are not thread safe and must be called from the main thread. This method was called from thread Thread-4.

# Fixed code
def fetch_and_execute_function_to_run(key, worker=global_worker):
    """Run on arbitrary function on the worker."""
    driver_id, serialized_function = worker.redis_client.hmget(
        key, ["driver_id", "function"]
    )

    if (
        worker.mode in [SCRIPT_MODE, SILENT_MODE]
        and driver_id != worker.task_driver_id.id()
    ):
        # This export was from a different driver and there's no need for this
        # driver to import it.
        return

    try:
        # Deserialize the function.
        function = pickle.loads(serialized_function)
        # Run the function.
        function({"worker": worker})
    except Exception:
        # If an exception was thrown when the function was run, we record the
        # traceback and notify the scheduler of the failure.
        traceback_str = traceback.format_exc()
        # Log the error message.
        name = (
            function.__name__
            if ("function" in locals() and hasattr(function, "__name__"))
            else ""
        )
        ray.utils.push_error_to_driver(
            worker.redis_client,
            "function_to_run",
            traceback_str,
            driver_id=driver_id,
            data={"name": name},
        )