We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Logging mode leaves a hanging thread in interactive python session
### System information
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: MacOS Monterey
- **Modin version** (`modin.__version__`): latest source
- **Python version**: 3.9.12
- **Code we can use to reproduce**:

In ipython, run 

```python
from modin.config import LogMode
import modin.pandas as pd

LogMode.enable()
df = pd.DataFrame([[1]])
```

and try to exit. You have to control-c or control-d twice.

This bug came up in the discussion on #4372 but it wasn't fixed in that PR.

The problematic thread is started [here](https://github.com/modin-project/modin/blob/49fc2cf3733f20ac6cf8a7c61e42ef7aa5cf4b03/modin/logging/config.py#L127).


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `modin/logging/config.py`
Content:
```
1 # Licensed to Modin Development Team under one or more contributor license agreements.
2 # See the NOTICE file distributed with this work for additional information regarding
3 # copyright ownership.  The Modin Development Team licenses this file to you under the
4 # Apache License, Version 2.0 (the "License"); you may not use this file except in
5 # compliance with the License.  You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software distributed under
10 # the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11 # ANY KIND, either express or implied. See the License for the specific language
12 # governing permissions and limitations under the License.
13 
14 """
15 Module contains ``ModinFormatter`` class.
16 
17 ``ModinFormatter`` and the associated functions are used for logging configuration.
18 """
19 
20 import logging
21 import datetime as dt
22 import os
23 import uuid
24 import platform
25 import psutil
26 import pkg_resources
27 import threading
28 import time
29 from modin.config import LogMemoryInterval, LogMode
30 
31 __LOGGER_CONFIGURED__: bool = False
32 
33 
34 class ModinFormatter(logging.Formatter):  # noqa: PR01
35     """Implement custom formatter to log at microsecond granularity."""
36 
37     def formatTime(self, record, datefmt=None):
38         """
39         Return the creation time of the specified LogRecord as formatted text.
40 
41         This custom logging formatter inherits from the logging module and
42         records timestamps at the microsecond level of granularity.
43 
44         Parameters
45         ----------
46         record : LogRecord
47             The specified LogRecord object.
48         datefmt : str, default: None
49             Used with time.ststrftime() to format time record.
50 
51         Returns
52         -------
53         datetime
54             Datetime object containing microsecond timestamp.
55         """
56         ct = dt.datetime.fromtimestamp(record.created)
57         if datefmt:
58             s = ct.strftime(datefmt)
59         else:
60             # Format datetime object ct to microseconds
61             t = ct.strftime("%Y-%m-%d %H:%M:%S")
62             s = f"{t},{record.msecs:03}"
63         return s
64 
65 
66 def bytes_int_to_str(num_bytes, suffix="B"):
67     """
68     Scale bytes to its human-readable format (e.g: 1253656678 => '1.17GB').
69 
70     Parameters
71     ----------
72     num_bytes : int
73         Number of bytes.
74     suffix : str, default: "B"
75         Suffix to add to conversion of num_bytes.
76 
77     Returns
78     -------
79     str
80         Human-readable string format.
81     """
82     factor = 1000
83     for unit in ["", "K", "M", "G", "T", "P"]:
84         if num_bytes < factor:
85             return f"{num_bytes:.2f}{unit}{suffix}"
86         num_bytes /= factor
87     return f"{num_bytes:.2f}{1000+P}{suffix}"
88 
89 
90 def configure_logging():
91     """Configure Modin logging by setting up directory structure and formatting."""
92     global __LOGGER_CONFIGURED__
93     logger = logging.getLogger("modin.logger")
94     job_id = uuid.uuid4().hex
95     log_filename = f".modin/logs/job_{job_id}.log"
96 
97     os.makedirs(os.path.dirname(log_filename), exist_ok=True)
98 
99     logfile = logging.FileHandler(log_filename, "a")
100     formatter = ModinFormatter(
101         fmt="%(process)d, %(thread)d, %(asctime)s, %(message)s",
102         datefmt="%Y-%m-%d,%H:%M:%S.%f",
103     )
104     logfile.setFormatter(formatter)
105     logger.addHandler(logfile)
106 
107     if LogMode.get() == "enable_api_only":
108         logger.setLevel(logging.INFO)
109     logger.setLevel(logging.DEBUG)
110 
111     logger = logging.getLogger("modin.logger")
112     logger.info(f"OS Version: {platform.platform()}")
113     logger.info(f"Python Version: {platform.python_version()}")
114     modin_version = pkg_resources.get_distribution("modin").version
115     pandas_version = pkg_resources.get_distribution("pandas").version
116     num_physical_cores = str(psutil.cpu_count(logical=False))
117     num_total_cores = str(psutil.cpu_count(logical=True))
118     svmem = psutil.virtual_memory()
119     logger.info(f"Modin Version: {modin_version}")
120     logger.info(f"Pandas Version: {pandas_version}")
121     logger.info(f"Physical Cores: {num_physical_cores}")
122     logger.info(f"Total Cores: {num_total_cores}")
123     logger.info(f"Memory Total: {bytes_int_to_str(svmem.total)}")
124     logger.info(f"Memory Available: {bytes_int_to_str(svmem.available)}")
125     logger.info(f"Memory Used: {bytes_int_to_str(svmem.used)}")
126 
127     if LogMode.get() != "enable_api_only":
128         mem_sleep = LogMemoryInterval.get()
129         mem = threading.Thread(target=memory_thread, args=[logger, mem_sleep])
130         mem.start()
131 
132     __LOGGER_CONFIGURED__ = True
133 
134 
135 def memory_thread(logger, sleep_time):
136     """
137     Configure Modin logging system memory profiling thread.
138 
139     Parameters
140     ----------
141     logger : logging.Logger
142         The logger object.
143     sleep_time : int
144         The interval at which to profile system memory.
145     """
146     while True:
147         svmem = psutil.virtual_memory()
148         logger.info(f"Memory Percentage: {svmem.percent}%")
149         time.sleep(sleep_time)
150 
151 
152 def get_logger():
153     """
154     Configure Modin logger based on Modin config and returns the logger.
155 
156     Returns
157     -------
158     logging.Logger
159         The Modin logger.
160     """
161     if not __LOGGER_CONFIGURED__ and LogMode.get() != "disable":
162         configure_logging()
163     return logging.getLogger("modin.logger")
164
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/modin/logging/config.py b/modin/logging/config.py
--- a/modin/logging/config.py
+++ b/modin/logging/config.py
@@ -126,7 +126,9 @@
 
     if LogMode.get() != "enable_api_only":
         mem_sleep = LogMemoryInterval.get()
-        mem = threading.Thread(target=memory_thread, args=[logger, mem_sleep])
+        mem = threading.Thread(
+            target=memory_thread, args=[logger, mem_sleep], daemon=True
+        )
         mem.start()
 
     __LOGGER_CONFIGURED__ = True

{"golden_diff": "diff --git a/modin/logging/config.py b/modin/logging/config.py\n--- a/modin/logging/config.py\n+++ b/modin/logging/config.py\n@@ -126,7 +126,9 @@\n \n     if LogMode.get() != \"enable_api_only\":\n         mem_sleep = LogMemoryInterval.get()\n-        mem = threading.Thread(target=memory_thread, args=[logger, mem_sleep])\n+        mem = threading.Thread(\n+            target=memory_thread, args=[logger, mem_sleep], daemon=True\n+        )\n         mem.start()\n \n     __LOGGER_CONFIGURED__ = True\n", "issue": "Logging mode leaves a hanging thread in interactive python session\n### System information\r\n- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: MacOS Monterey\r\n- **Modin version** (`modin.__version__`): latest source\r\n- **Python version**: 3.9.12\r\n- **Code we can use to reproduce**:\r\n\r\nIn ipython, run \r\n\r\n```python\r\nfrom modin.config import LogMode\r\nimport modin.pandas as pd\r\n\r\nLogMode.enable()\r\ndf = pd.DataFrame([[1]])\r\n```\r\n\r\nand try to exit. You have to control-c or control-d twice.\r\n\r\nThis bug came up in the discussion on #4372 but it wasn't fixed in that PR.\r\n\r\nThe problematic thread is started [here](https://github.com/modin-project/modin/blob/49fc2cf3733f20ac6cf8a7c61e42ef7aa5cf4b03/modin/logging/config.py#L127).\r\n\n", "before_files": [{"content": "# Licensed to Modin Development Team under one or more contributor license agreements.\n# See the NOTICE file distributed with this work for additional information regarding\n# copyright ownership.  The Modin Development Team licenses this file to you under the\n# Apache License, Version 2.0 (the \"License\"); you may not use this file except in\n# compliance with the License.  You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software distributed under\n# the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n# ANY KIND, either express or implied. See the License for the specific language\n# governing permissions and limitations under the License.\n\n\"\"\"\nModule contains ``ModinFormatter`` class.\n\n``ModinFormatter`` and the associated functions are used for logging configuration.\n\"\"\"\n\nimport logging\nimport datetime as dt\nimport os\nimport uuid\nimport platform\nimport psutil\nimport pkg_resources\nimport threading\nimport time\nfrom modin.config import LogMemoryInterval, LogMode\n\n__LOGGER_CONFIGURED__: bool = False\n\n\nclass ModinFormatter(logging.Formatter):  # noqa: PR01\n    \"\"\"Implement custom formatter to log at microsecond granularity.\"\"\"\n\n    def formatTime(self, record, datefmt=None):\n        \"\"\"\n        Return the creation time of the specified LogRecord as formatted text.\n\n        This custom logging formatter inherits from the logging module and\n        records timestamps at the microsecond level of granularity.\n\n        Parameters\n        ----------\n        record : LogRecord\n            The specified LogRecord object.\n        datefmt : str, default: None\n            Used with time.ststrftime() to format time record.\n\n        Returns\n        -------\n        datetime\n            Datetime object containing microsecond timestamp.\n        \"\"\"\n        ct = dt.datetime.fromtimestamp(record.created)\n        if datefmt:\n            s = ct.strftime(datefmt)\n        else:\n            # Format datetime object ct to microseconds\n            t = ct.strftime(\"%Y-%m-%d %H:%M:%S\")\n            s = f\"{t},{record.msecs:03}\"\n        return s\n\n\ndef bytes_int_to_str(num_bytes, suffix=\"B\"):\n    \"\"\"\n    Scale bytes to its human-readable format (e.g: 1253656678 => '1.17GB').\n\n    Parameters\n    ----------\n    num_bytes : int\n        Number of bytes.\n    suffix : str, default: \"B\"\n        Suffix to add to conversion of num_bytes.\n\n    Returns\n    -------\n    str\n        Human-readable string format.\n    \"\"\"\n    factor = 1000\n    for unit in [\"\", \"K\", \"M\", \"G\", \"T\", \"P\"]:\n        if num_bytes < factor:\n            return f\"{num_bytes:.2f}{unit}{suffix}\"\n        num_bytes /= factor\n    return f\"{num_bytes:.2f}{1000+P}{suffix}\"\n\n\ndef configure_logging():\n    \"\"\"Configure Modin logging by setting up directory structure and formatting.\"\"\"\n    global __LOGGER_CONFIGURED__\n    logger = logging.getLogger(\"modin.logger\")\n    job_id = uuid.uuid4().hex\n    log_filename = f\".modin/logs/job_{job_id}.log\"\n\n    os.makedirs(os.path.dirname(log_filename), exist_ok=True)\n\n    logfile = logging.FileHandler(log_filename, \"a\")\n    formatter = ModinFormatter(\n        fmt=\"%(process)d, %(thread)d, %(asctime)s, %(message)s\",\n        datefmt=\"%Y-%m-%d,%H:%M:%S.%f\",\n    )\n    logfile.setFormatter(formatter)\n    logger.addHandler(logfile)\n\n    if LogMode.get() == \"enable_api_only\":\n        logger.setLevel(logging.INFO)\n    logger.setLevel(logging.DEBUG)\n\n    logger = logging.getLogger(\"modin.logger\")\n    logger.info(f\"OS Version: {platform.platform()}\")\n    logger.info(f\"Python Version: {platform.python_version()}\")\n    modin_version = pkg_resources.get_distribution(\"modin\").version\n    pandas_version = pkg_resources.get_distribution(\"pandas\").version\n    num_physical_cores = str(psutil.cpu_count(logical=False))\n    num_total_cores = str(psutil.cpu_count(logical=True))\n    svmem = psutil.virtual_memory()\n    logger.info(f\"Modin Version: {modin_version}\")\n    logger.info(f\"Pandas Version: {pandas_version}\")\n    logger.info(f\"Physical Cores: {num_physical_cores}\")\n    logger.info(f\"Total Cores: {num_total_cores}\")\n    logger.info(f\"Memory Total: {bytes_int_to_str(svmem.total)}\")\n    logger.info(f\"Memory Available: {bytes_int_to_str(svmem.available)}\")\n    logger.info(f\"Memory Used: {bytes_int_to_str(svmem.used)}\")\n\n    if LogMode.get() != \"enable_api_only\":\n        mem_sleep = LogMemoryInterval.get()\n        mem = threading.Thread(target=memory_thread, args=[logger, mem_sleep])\n        mem.start()\n\n    __LOGGER_CONFIGURED__ = True\n\n\ndef memory_thread(logger, sleep_time):\n    \"\"\"\n    Configure Modin logging system memory profiling thread.\n\n    Parameters\n    ----------\n    logger : logging.Logger\n        The logger object.\n    sleep_time : int\n        The interval at which to profile system memory.\n    \"\"\"\n    while True:\n        svmem = psutil.virtual_memory()\n        logger.info(f\"Memory Percentage: {svmem.percent}%\")\n        time.sleep(sleep_time)\n\n\ndef get_logger():\n    \"\"\"\n    Configure Modin logger based on Modin config and returns the logger.\n\n    Returns\n    -------\n    logging.Logger\n        The Modin logger.\n    \"\"\"\n    if not __LOGGER_CONFIGURED__ and LogMode.get() != \"disable\":\n        configure_logging()\n    return logging.getLogger(\"modin.logger\")\n", "path": "modin/logging/config.py"}], "after_files": [{"content": "# Licensed to Modin Development Team under one or more contributor license agreements.\n# See the NOTICE file distributed with this work for additional information regarding\n# copyright ownership.  The Modin Development Team licenses this file to you under the\n# Apache License, Version 2.0 (the \"License\"); you may not use this file except in\n# compliance with the License.  You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software distributed under\n# the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n# ANY KIND, either express or implied. See the License for the specific language\n# governing permissions and limitations under the License.\n\n\"\"\"\nModule contains ``ModinFormatter`` class.\n\n``ModinFormatter`` and the associated functions are used for logging configuration.\n\"\"\"\n\nimport logging\nimport datetime as dt\nimport os\nimport uuid\nimport platform\nimport psutil\nimport pkg_resources\nimport threading\nimport time\nfrom modin.config import LogMemoryInterval, LogMode\n\n__LOGGER_CONFIGURED__: bool = False\n\n\nclass ModinFormatter(logging.Formatter):  # noqa: PR01\n    \"\"\"Implement custom formatter to log at microsecond granularity.\"\"\"\n\n    def formatTime(self, record, datefmt=None):\n        \"\"\"\n        Return the creation time of the specified LogRecord as formatted text.\n\n        This custom logging formatter inherits from the logging module and\n        records timestamps at the microsecond level of granularity.\n\n        Parameters\n        ----------\n        record : LogRecord\n            The specified LogRecord object.\n        datefmt : str, default: None\n            Used with time.ststrftime() to format time record.\n\n        Returns\n        -------\n        datetime\n            Datetime object containing microsecond timestamp.\n        \"\"\"\n        ct = dt.datetime.fromtimestamp(record.created)\n        if datefmt:\n            s = ct.strftime(datefmt)\n        else:\n            # Format datetime object ct to microseconds\n            t = ct.strftime(\"%Y-%m-%d %H:%M:%S\")\n            s = f\"{t},{record.msecs:03}\"\n        return s\n\n\ndef bytes_int_to_str(num_bytes, suffix=\"B\"):\n    \"\"\"\n    Scale bytes to its human-readable format (e.g: 1253656678 => '1.17GB').\n\n    Parameters\n    ----------\n    num_bytes : int\n        Number of bytes.\n    suffix : str, default: \"B\"\n        Suffix to add to conversion of num_bytes.\n\n    Returns\n    -------\n    str\n        Human-readable string format.\n    \"\"\"\n    factor = 1000\n    for unit in [\"\", \"K\", \"M\", \"G\", \"T\", \"P\"]:\n        if num_bytes < factor:\n            return f\"{num_bytes:.2f}{unit}{suffix}\"\n        num_bytes /= factor\n    return f\"{num_bytes:.2f}{1000+P}{suffix}\"\n\n\ndef configure_logging():\n    \"\"\"Configure Modin logging by setting up directory structure and formatting.\"\"\"\n    global __LOGGER_CONFIGURED__\n    logger = logging.getLogger(\"modin.logger\")\n    job_id = uuid.uuid4().hex\n    log_filename = f\".modin/logs/job_{job_id}.log\"\n\n    os.makedirs(os.path.dirname(log_filename), exist_ok=True)\n\n    logfile = logging.FileHandler(log_filename, \"a\")\n    formatter = ModinFormatter(\n        fmt=\"%(process)d, %(thread)d, %(asctime)s, %(message)s\",\n        datefmt=\"%Y-%m-%d,%H:%M:%S.%f\",\n    )\n    logfile.setFormatter(formatter)\n    logger.addHandler(logfile)\n\n    if LogMode.get() == \"enable_api_only\":\n        logger.setLevel(logging.INFO)\n    logger.setLevel(logging.DEBUG)\n\n    logger = logging.getLogger(\"modin.logger\")\n    logger.info(f\"OS Version: {platform.platform()}\")\n    logger.info(f\"Python Version: {platform.python_version()}\")\n    modin_version = pkg_resources.get_distribution(\"modin\").version\n    pandas_version = pkg_resources.get_distribution(\"pandas\").version\n    num_physical_cores = str(psutil.cpu_count(logical=False))\n    num_total_cores = str(psutil.cpu_count(logical=True))\n    svmem = psutil.virtual_memory()\n    logger.info(f\"Modin Version: {modin_version}\")\n    logger.info(f\"Pandas Version: {pandas_version}\")\n    logger.info(f\"Physical Cores: {num_physical_cores}\")\n    logger.info(f\"Total Cores: {num_total_cores}\")\n    logger.info(f\"Memory Total: {bytes_int_to_str(svmem.total)}\")\n    logger.info(f\"Memory Available: {bytes_int_to_str(svmem.available)}\")\n    logger.info(f\"Memory Used: {bytes_int_to_str(svmem.used)}\")\n\n    if LogMode.get() != \"enable_api_only\":\n        mem_sleep = LogMemoryInterval.get()\n        mem = threading.Thread(\n            target=memory_thread, args=[logger, mem_sleep], daemon=True\n        )\n        mem.start()\n\n    __LOGGER_CONFIGURED__ = True\n\n\ndef memory_thread(logger, sleep_time):\n    \"\"\"\n    Configure Modin logging system memory profiling thread.\n\n    Parameters\n    ----------\n    logger : logging.Logger\n        The logger object.\n    sleep_time : int\n        The interval at which to profile system memory.\n    \"\"\"\n    while True:\n        svmem = psutil.virtual_memory()\n        logger.info(f\"Memory Percentage: {svmem.percent}%\")\n        time.sleep(sleep_time)\n\n\ndef get_logger():\n    \"\"\"\n    Configure Modin logger based on Modin config and returns the logger.\n\n    Returns\n    -------\n    logging.Logger\n        The Modin logger.\n    \"\"\"\n    if not __LOGGER_CONFIGURED__ and LogMode.get() != \"disable\":\n        configure_logging()\n    return logging.getLogger(\"modin.logger\")\n", "path": "modin/logging/config.py"}]}