prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Bug: Deadlock 'fix' introduced deadlock.
  Since https://github.com/open-mmlab/mmcv/pull/252 is merged my mmdetection code hangs after evaluation. After reverting the specific commit `git revert c203419f57c2e25ab4307420b9a3688f99e01dea`, my code runs again as expected..
  
  </issue>
  <code>
  [start of mmcv/runner/hooks/logger/text.py]
  1 # Copyright (c) Open-MMLab. All rights reserved.
  2 import datetime
  3 import os.path as osp
  4 from collections import OrderedDict
  5 
  6 import torch
  7 import torch.distributed as dist
  8 
  9 import mmcv
  10 from ..hook import HOOKS
  11 from .base import LoggerHook
  12 
  13 
  14 @HOOKS.register_module
  15 class TextLoggerHook(LoggerHook):
  16 
  17     def __init__(self, interval=10, ignore_last=True, reset_flag=False):
  18         super(TextLoggerHook, self).__init__(interval, ignore_last, reset_flag)
  19         self.time_sec_tot = 0
  20 
  21     def before_run(self, runner):
  22         super(TextLoggerHook, self).before_run(runner)
  23         self.start_iter = runner.iter
  24         self.json_log_path = osp.join(runner.work_dir,
  25                                       f'{runner.timestamp}.log.json')
  26         if runner.meta is not None:
  27             self._dump_log(runner.meta, runner)
  28 
  29     def _get_max_memory(self, runner):
  30         mem = torch.cuda.max_memory_allocated()
  31         mem_mb = torch.tensor([mem / (1024 * 1024)],
  32                               dtype=torch.int,
  33                               device=torch.device('cuda'))
  34         if runner.world_size > 1:
  35             dist.reduce(mem_mb, 0, op=dist.ReduceOp.MAX)
  36         return mem_mb.item()
  37 
  38     def _log_info(self, log_dict, runner):
  39         if runner.mode == 'train':
  40             log_str = f'Epoch [{log_dict["epoch"]}]' \
  41                       f'[{log_dict["iter"]}/{len(runner.data_loader)}]\t' \
  42                       f'lr: {log_dict["lr"]:.5f}, '
  43             if 'time' in log_dict.keys():
  44                 self.time_sec_tot += (log_dict['time'] * self.interval)
  45                 time_sec_avg = self.time_sec_tot / (
  46                     runner.iter - self.start_iter + 1)
  47                 eta_sec = time_sec_avg * (runner.max_iters - runner.iter - 1)
  48                 eta_str = str(datetime.timedelta(seconds=int(eta_sec)))
  49                 log_str += f'eta: {eta_str}, '
  50                 log_str += f'time: {log_dict["time"]:.3f}, ' \
  51                            f'data_time: {log_dict["data_time"]:.3f}, '
  52                 # statistic memory
  53                 if torch.cuda.is_available():
  54                     log_str += f'memory: {log_dict["memory"]}, '
  55         else:
  56             log_str = 'Epoch({log_dict["mode"]}) ' \
  57                       f'[{log_dict["epoch"] - 1}][{log_dict["iter"]}]\t'
  58         log_items = []
  59         for name, val in log_dict.items():
  60             # TODO: resolve this hack
  61             # these items have been in log_str
  62             if name in [
  63                     'mode', 'Epoch', 'iter', 'lr', 'time', 'data_time',
  64                     'memory', 'epoch'
  65             ]:
  66                 continue
  67             if isinstance(val, float):
  68                 val = f'{val:.4f}'
  69             log_items.append(f'{name}: {val}')
  70         log_str += ', '.join(log_items)
  71         runner.logger.info(log_str)
  72 
  73     def _dump_log(self, log_dict, runner):
  74         # dump log in json format
  75         json_log = OrderedDict()
  76         for k, v in log_dict.items():
  77             json_log[k] = self._round_float(v)
  78         # only append log at last line
  79         if runner.rank == 0:
  80             with open(self.json_log_path, 'a+') as f:
  81                 mmcv.dump(json_log, f, file_format='json')
  82                 f.write('\n')
  83 
  84     def _round_float(self, items):
  85         if isinstance(items, list):
  86             return [self._round_float(item) for item in items]
  87         elif isinstance(items, float):
  88             return round(items, 5)
  89         else:
  90             return items
  91 
  92     def log(self, runner):
  93         log_dict = OrderedDict()
  94         # training mode if the output contains the key "time"
  95         mode = 'train' if 'time' in runner.log_buffer.output else 'val'
  96         log_dict['mode'] = mode
  97         log_dict['epoch'] = runner.epoch + 1
  98         log_dict['iter'] = runner.inner_iter + 1
  99         # only record lr of the first param group
  100         log_dict['lr'] = runner.current_lr()[0]
  101         memory = None
  102         if torch.cuda.is_available():
  103             memory = self._get_max_memory(runner)
  104         if mode == 'train':
  105             log_dict['time'] = runner.log_buffer.output['time']
  106             log_dict['data_time'] = runner.log_buffer.output['data_time']
  107 
  108             # statistic memory
  109             if memory is not None:
  110                 log_dict['memory'] = memory
  111         for name, val in runner.log_buffer.output.items():
  112             if name in ['time', 'data_time']:
  113                 continue
  114             log_dict[name] = val
  115 
  116         self._log_info(log_dict, runner)
  117         self._dump_log(log_dict, runner)
  118
  [end of mmcv/runner/hooks/logger/text.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/mmcv/runner/hooks/logger/text.py b/mmcv/runner/hooks/logger/text.py
  --- a/mmcv/runner/hooks/logger/text.py
  +++ b/mmcv/runner/hooks/logger/text.py
  @@ -98,16 +98,13 @@
           log_dict['iter'] = runner.inner_iter + 1
           # only record lr of the first param group
           log_dict['lr'] = runner.current_lr()[0]
  -        memory = None
  -        if torch.cuda.is_available():
  -            memory = self._get_max_memory(runner)
           if mode == 'train':
               log_dict['time'] = runner.log_buffer.output['time']
               log_dict['data_time'] = runner.log_buffer.output['data_time']
   
               # statistic memory
  -            if memory is not None:
  -                log_dict['memory'] = memory
  +            if torch.cuda.is_available():
  +                log_dict['memory'] = self._get_max_memory(runner)
           for name, val in runner.log_buffer.output.items():
               if name in ['time', 'data_time']:
                   continue
  
verification_info: {"golden_diff": "diff --git a/mmcv/runner/hooks/logger/text.py b/mmcv/runner/hooks/logger/text.py\n--- a/mmcv/runner/hooks/logger/text.py\n+++ b/mmcv/runner/hooks/logger/text.py\n@@ -98,16 +98,13 @@\n         log_dict['iter'] = runner.inner_iter + 1\n         # only record lr of the first param group\n         log_dict['lr'] = runner.current_lr()[0]\n-        memory = None\n-        if torch.cuda.is_available():\n-            memory = self._get_max_memory(runner)\n         if mode == 'train':\n             log_dict['time'] = runner.log_buffer.output['time']\n             log_dict['data_time'] = runner.log_buffer.output['data_time']\n \n             # statistic memory\n-            if memory is not None:\n-                log_dict['memory'] = memory\n+            if torch.cuda.is_available():\n+                log_dict['memory'] = self._get_max_memory(runner)\n         for name, val in runner.log_buffer.output.items():\n             if name in ['time', 'data_time']:\n                 continue\n", "issue": "Bug: Deadlock 'fix' introduced deadlock.\nSince https://github.com/open-mmlab/mmcv/pull/252 is merged my mmdetection code hangs after evaluation. After reverting the specific commit `git revert c203419f57c2e25ab4307420b9a3688f99e01dea`, my code runs again as expected..\n", "before_files": [{"content": "# Copyright (c) Open-MMLab. All rights reserved.\nimport datetime\nimport os.path as osp\nfrom collections import OrderedDict\n\nimport torch\nimport torch.distributed as dist\n\nimport mmcv\nfrom ..hook import HOOKS\nfrom .base import LoggerHook\n\n\n@HOOKS.register_module\nclass TextLoggerHook(LoggerHook):\n\n    def __init__(self, interval=10, ignore_last=True, reset_flag=False):\n        super(TextLoggerHook, self).__init__(interval, ignore_last, reset_flag)\n        self.time_sec_tot = 0\n\n    def before_run(self, runner):\n        super(TextLoggerHook, self).before_run(runner)\n        self.start_iter = runner.iter\n        self.json_log_path = osp.join(runner.work_dir,\n                                      f'{runner.timestamp}.log.json')\n        if runner.meta is not None:\n            self._dump_log(runner.meta, runner)\n\n    def _get_max_memory(self, runner):\n        mem = torch.cuda.max_memory_allocated()\n        mem_mb = torch.tensor([mem / (1024 * 1024)],\n                              dtype=torch.int,\n                              device=torch.device('cuda'))\n        if runner.world_size > 1:\n            dist.reduce(mem_mb, 0, op=dist.ReduceOp.MAX)\n        return mem_mb.item()\n\n    def _log_info(self, log_dict, runner):\n        if runner.mode == 'train':\n            log_str = f'Epoch [{log_dict[\"epoch\"]}]' \\\n                      f'[{log_dict[\"iter\"]}/{len(runner.data_loader)}]\\t' \\\n                      f'lr: {log_dict[\"lr\"]:.5f}, '\n            if 'time' in log_dict.keys():\n                self.time_sec_tot += (log_dict['time'] * self.interval)\n                time_sec_avg = self.time_sec_tot / (\n                    runner.iter - self.start_iter + 1)\n                eta_sec = time_sec_avg * (runner.max_iters - runner.iter - 1)\n                eta_str = str(datetime.timedelta(seconds=int(eta_sec)))\n                log_str += f'eta: {eta_str}, '\n                log_str += f'time: {log_dict[\"time\"]:.3f}, ' \\\n                           f'data_time: {log_dict[\"data_time\"]:.3f}, '\n                # statistic memory\n                if torch.cuda.is_available():\n                    log_str += f'memory: {log_dict[\"memory\"]}, '\n        else:\n            log_str = 'Epoch({log_dict[\"mode\"]}) ' \\\n                      f'[{log_dict[\"epoch\"] - 1}][{log_dict[\"iter\"]}]\\t'\n        log_items = []\n        for name, val in log_dict.items():\n            # TODO: resolve this hack\n            # these items have been in log_str\n            if name in [\n                    'mode', 'Epoch', 'iter', 'lr', 'time', 'data_time',\n                    'memory', 'epoch'\n            ]:\n                continue\n            if isinstance(val, float):\n                val = f'{val:.4f}'\n            log_items.append(f'{name}: {val}')\n        log_str += ', '.join(log_items)\n        runner.logger.info(log_str)\n\n    def _dump_log(self, log_dict, runner):\n        # dump log in json format\n        json_log = OrderedDict()\n        for k, v in log_dict.items():\n            json_log[k] = self._round_float(v)\n        # only append log at last line\n        if runner.rank == 0:\n            with open(self.json_log_path, 'a+') as f:\n                mmcv.dump(json_log, f, file_format='json')\n                f.write('\\n')\n\n    def _round_float(self, items):\n        if isinstance(items, list):\n            return [self._round_float(item) for item in items]\n        elif isinstance(items, float):\n            return round(items, 5)\n        else:\n            return items\n\n    def log(self, runner):\n        log_dict = OrderedDict()\n        # training mode if the output contains the key \"time\"\n        mode = 'train' if 'time' in runner.log_buffer.output else 'val'\n        log_dict['mode'] = mode\n        log_dict['epoch'] = runner.epoch + 1\n        log_dict['iter'] = runner.inner_iter + 1\n        # only record lr of the first param group\n        log_dict['lr'] = runner.current_lr()[0]\n        memory = None\n        if torch.cuda.is_available():\n            memory = self._get_max_memory(runner)\n        if mode == 'train':\n            log_dict['time'] = runner.log_buffer.output['time']\n            log_dict['data_time'] = runner.log_buffer.output['data_time']\n\n            # statistic memory\n            if memory is not None:\n                log_dict['memory'] = memory\n        for name, val in runner.log_buffer.output.items():\n            if name in ['time', 'data_time']:\n                continue\n            log_dict[name] = val\n\n        self._log_info(log_dict, runner)\n        self._dump_log(log_dict, runner)\n", "path": "mmcv/runner/hooks/logger/text.py"}]}