We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
--autoreload raises AttributeError: 'NoneType' object has no attribute 'stop'
I'm on the current Panel master. When I `panel serve 'script.py' --autoreload` this code

```python
import panel as pn
pn.extension()

import numpy as np
import holoviews as hv

from holoviews import opts, streams
from holoviews.plotting.links import DataLink

hv.extension('bokeh')
curve = hv.Curve(np.random.randn(10).cumsum()).opts(responsive=True, line_width=6)
table = hv.Table(curve).opts(editable=True)
component=pn.pane.HoloViews(table, height=500, sizing_mode="stretch_both")
pn.template.FastListTemplate(title="Table", main=[component]).servable()
```

and change the code I get the error

```bash
2021-08-04 06:40:44,760 Error thrown from periodic callback:
2021-08-04 06:40:44,763 Traceback (most recent call last):
  File "c:\repos\private\panel_docker\panel\.venv\lib\site-packages\tornado\gen.py", line 526, in callback
    result_list.append(f.result())
  File "c:\repos\private\panel_docker\panel\.venv\lib\site-packages\bokeh\server\session.py", line 67, in _needs_document_lock_wrapper
    result = func(self, *args, **kwargs)
  File "c:\repos\private\panel_docker\panel\.venv\lib\site-packages\bokeh\server\session.py", line 195, in with_document_locked
    return func(*args, **kwargs)
  File "c:\repos\private\panel_docker\panel\.venv\lib\site-packages\bokeh\document\document.py", line 1212, in wrapper
    return doc._with_self_as_curdoc(invoke)
  File "c:\repos\private\panel_docker\panel\.venv\lib\site-packages\bokeh\document\document.py", line 1198, in _with_self_as_curdoc
    return f()
  File "c:\repos\private\panel_docker\panel\.venv\lib\site-packages\bokeh\document\document.py", line 1211, in invoke
    return f(*args, **kwargs)
  File "c:\repos\private\panel_docker\panel\panel\io\callbacks.py", line 72, in _periodic_callback
    self.callback()
  File "c:\repos\private\panel_docker\panel\panel\io\reload.py", line 155, in _reload_on_update
    _check_file(modify_times, path)
  File "c:\repos\private\panel_docker\panel\panel\io\reload.py", line 134, in _check_file
    _reload(module)
  File "c:\repos\private\panel_docker\panel\panel\io\reload.py", line 117, in _reload
    cb.stop()
  File "c:\repos\private\panel_docker\panel\panel\io\callbacks.py", line 134, in stop
    self._cb.stop()
AttributeError: 'NoneType' object has no attribute 'stop'
```

I believe this is would be a major issue if 0.12.1 was released before fixing this @philippjfr 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `panel/io/callbacks.py`
Content:
```
1 """
2 Defines callbacks to be executed on a thread or by scheduling it
3 on a running bokeh server.
4 """
5 import time
6 import param
7 
8 from bokeh.io import curdoc as _curdoc
9 
10 from ..util import edit_readonly
11 from .state import state
12 
13 
14 class PeriodicCallback(param.Parameterized):
15     """
16     Periodic encapsulates a periodic callback which will run both
17     in tornado based notebook environments and on bokeh server. By
18     default the callback will run until the stop method is called,
19     but count and timeout values can be set to limit the number of
20     executions or the maximum length of time for which the callback
21     will run. The callback may also be started and stopped by setting
22     the running parameter to True or False respectively.
23     """
24 
25     callback = param.Callable(doc="""
26         The callback to execute periodically.""")
27 
28     count = param.Integer(default=None, doc="""
29         Number of times the callback will be executed, by default
30         this is unlimited.""")
31 
32     period = param.Integer(default=500, doc="""
33         Period in milliseconds at which the callback is executed.""")
34 
35     timeout = param.Integer(default=None, doc="""
36         Timeout in milliseconds from the start time at which the callback
37         expires.""")
38 
39     running = param.Boolean(default=False, doc="""
40         Toggles whether the periodic callback is currently running.""")
41 
42     def __init__(self, **params):
43         super().__init__(**params)
44         self._counter = 0
45         self._start_time = None
46         self._cb = None
47         self._updating = False
48         self._doc = None
49 
50     @param.depends('running', watch=True)
51     def _start(self):
52         if not self.running or self._updating:
53             return
54         self.start()
55 
56     @param.depends('running', watch=True)
57     def _stop(self):
58         if self.running or self._updating:
59             return
60         self.stop()
61 
62     @param.depends('period', watch=True)
63     def _update_period(self):
64         if self._cb:
65             self.stop()
66             self.start()
67 
68     def _periodic_callback(self):
69         with edit_readonly(state):
70             state.busy = True
71         try:
72             self.callback()
73         finally:
74             with edit_readonly(state):
75                 state.busy = False
76         self._counter += 1
77         if self.timeout is not None:
78             dt = (time.time() - self._start_time) * 1000
79             if dt > self.timeout:
80                 self.stop()
81         if self._counter == self.count:
82             self.stop()
83 
84     @property
85     def counter(self):
86         """
87         Returns the execution count of the periodic callback.
88         """
89         return self._counter
90 
91     def _cleanup(self, session_context):
92         self.stop()
93 
94     def start(self):
95         """
96         Starts running the periodic callback.
97         """
98         if self._cb is not None:
99             raise RuntimeError('Periodic callback has already started.')
100         if not self.running:
101             try:
102                 self._updating = True
103                 self.running = True
104             finally:
105                 self._updating = False
106         self._start_time = time.time()
107         if state.curdoc:
108             self._doc = state.curdoc
109             self._cb = self._doc.add_periodic_callback(self._periodic_callback, self.period)
110         else:
111             from tornado.ioloop import PeriodicCallback
112             self._cb = PeriodicCallback(self._periodic_callback, self.period)
113             self._cb.start()
114         try:
115             state.on_session_destroyed(self._cleanup)
116         except Exception:
117             pass
118 
119     def stop(self):
120         """
121         Stops running the periodic callback.
122         """
123         if self.running:
124             try:
125                 self._updating = True
126                 self.running = False
127             finally:
128                 self._updating = False
129         self._counter = 0
130         self._timeout = None
131         if self._doc:
132             self._doc.remove_periodic_callback(self._cb)
133         else:
134             self._cb.stop()
135         self._cb = None
136         doc = self._doc or _curdoc()
137         if doc:
138             doc.session_destroyed_callbacks = {
139                 cb for cb in doc.session_destroyed_callbacks
140                 if cb is not self._cleanup
141             }
142             self._doc = None
143
```
--- 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/panel/io/callbacks.py b/panel/io/callbacks.py
--- a/panel/io/callbacks.py
+++ b/panel/io/callbacks.py
@@ -130,7 +130,7 @@
         self._timeout = None
         if self._doc:
             self._doc.remove_periodic_callback(self._cb)
-        else:
+        elif self._cb:
             self._cb.stop()
         self._cb = None
         doc = self._doc or _curdoc()

{"golden_diff": "diff --git a/panel/io/callbacks.py b/panel/io/callbacks.py\n--- a/panel/io/callbacks.py\n+++ b/panel/io/callbacks.py\n@@ -130,7 +130,7 @@\n         self._timeout = None\n         if self._doc:\n             self._doc.remove_periodic_callback(self._cb)\n-        else:\n+        elif self._cb:\n             self._cb.stop()\n         self._cb = None\n         doc = self._doc or _curdoc()\n", "issue": "--autoreload raises AttributeError: 'NoneType' object has no attribute 'stop'\nI'm on the current Panel master. When I `panel serve 'script.py' --autoreload` this code\r\n\r\n```python\r\nimport panel as pn\r\npn.extension()\r\n\r\nimport numpy as np\r\nimport holoviews as hv\r\n\r\nfrom holoviews import opts, streams\r\nfrom holoviews.plotting.links import DataLink\r\n\r\nhv.extension('bokeh')\r\ncurve = hv.Curve(np.random.randn(10).cumsum()).opts(responsive=True, line_width=6)\r\ntable = hv.Table(curve).opts(editable=True)\r\ncomponent=pn.pane.HoloViews(table, height=500, sizing_mode=\"stretch_both\")\r\npn.template.FastListTemplate(title=\"Table\", main=[component]).servable()\r\n```\r\n\r\nand change the code I get the error\r\n\r\n```bash\r\n2021-08-04 06:40:44,760 Error thrown from periodic callback:\r\n2021-08-04 06:40:44,763 Traceback (most recent call last):\r\n  File \"c:\\repos\\private\\panel_docker\\panel\\.venv\\lib\\site-packages\\tornado\\gen.py\", line 526, in callback\r\n    result_list.append(f.result())\r\n  File \"c:\\repos\\private\\panel_docker\\panel\\.venv\\lib\\site-packages\\bokeh\\server\\session.py\", line 67, in _needs_document_lock_wrapper\r\n    result = func(self, *args, **kwargs)\r\n  File \"c:\\repos\\private\\panel_docker\\panel\\.venv\\lib\\site-packages\\bokeh\\server\\session.py\", line 195, in with_document_locked\r\n    return func(*args, **kwargs)\r\n  File \"c:\\repos\\private\\panel_docker\\panel\\.venv\\lib\\site-packages\\bokeh\\document\\document.py\", line 1212, in wrapper\r\n    return doc._with_self_as_curdoc(invoke)\r\n  File \"c:\\repos\\private\\panel_docker\\panel\\.venv\\lib\\site-packages\\bokeh\\document\\document.py\", line 1198, in _with_self_as_curdoc\r\n    return f()\r\n  File \"c:\\repos\\private\\panel_docker\\panel\\.venv\\lib\\site-packages\\bokeh\\document\\document.py\", line 1211, in invoke\r\n    return f(*args, **kwargs)\r\n  File \"c:\\repos\\private\\panel_docker\\panel\\panel\\io\\callbacks.py\", line 72, in _periodic_callback\r\n    self.callback()\r\n  File \"c:\\repos\\private\\panel_docker\\panel\\panel\\io\\reload.py\", line 155, in _reload_on_update\r\n    _check_file(modify_times, path)\r\n  File \"c:\\repos\\private\\panel_docker\\panel\\panel\\io\\reload.py\", line 134, in _check_file\r\n    _reload(module)\r\n  File \"c:\\repos\\private\\panel_docker\\panel\\panel\\io\\reload.py\", line 117, in _reload\r\n    cb.stop()\r\n  File \"c:\\repos\\private\\panel_docker\\panel\\panel\\io\\callbacks.py\", line 134, in stop\r\n    self._cb.stop()\r\nAttributeError: 'NoneType' object has no attribute 'stop'\r\n```\r\n\r\nI believe this is would be a major issue if 0.12.1 was released before fixing this @philippjfr \n", "before_files": [{"content": "\"\"\"\nDefines callbacks to be executed on a thread or by scheduling it\non a running bokeh server.\n\"\"\"\nimport time\nimport param\n\nfrom bokeh.io import curdoc as _curdoc\n\nfrom ..util import edit_readonly\nfrom .state import state\n\n\nclass PeriodicCallback(param.Parameterized):\n    \"\"\"\n    Periodic encapsulates a periodic callback which will run both\n    in tornado based notebook environments and on bokeh server. By\n    default the callback will run until the stop method is called,\n    but count and timeout values can be set to limit the number of\n    executions or the maximum length of time for which the callback\n    will run. The callback may also be started and stopped by setting\n    the running parameter to True or False respectively.\n    \"\"\"\n\n    callback = param.Callable(doc=\"\"\"\n        The callback to execute periodically.\"\"\")\n\n    count = param.Integer(default=None, doc=\"\"\"\n        Number of times the callback will be executed, by default\n        this is unlimited.\"\"\")\n\n    period = param.Integer(default=500, doc=\"\"\"\n        Period in milliseconds at which the callback is executed.\"\"\")\n\n    timeout = param.Integer(default=None, doc=\"\"\"\n        Timeout in milliseconds from the start time at which the callback\n        expires.\"\"\")\n\n    running = param.Boolean(default=False, doc=\"\"\"\n        Toggles whether the periodic callback is currently running.\"\"\")\n\n    def __init__(self, **params):\n        super().__init__(**params)\n        self._counter = 0\n        self._start_time = None\n        self._cb = None\n        self._updating = False\n        self._doc = None\n\n    @param.depends('running', watch=True)\n    def _start(self):\n        if not self.running or self._updating:\n            return\n        self.start()\n\n    @param.depends('running', watch=True)\n    def _stop(self):\n        if self.running or self._updating:\n            return\n        self.stop()\n\n    @param.depends('period', watch=True)\n    def _update_period(self):\n        if self._cb:\n            self.stop()\n            self.start()\n\n    def _periodic_callback(self):\n        with edit_readonly(state):\n            state.busy = True\n        try:\n            self.callback()\n        finally:\n            with edit_readonly(state):\n                state.busy = False\n        self._counter += 1\n        if self.timeout is not None:\n            dt = (time.time() - self._start_time) * 1000\n            if dt > self.timeout:\n                self.stop()\n        if self._counter == self.count:\n            self.stop()\n\n    @property\n    def counter(self):\n        \"\"\"\n        Returns the execution count of the periodic callback.\n        \"\"\"\n        return self._counter\n\n    def _cleanup(self, session_context):\n        self.stop()\n\n    def start(self):\n        \"\"\"\n        Starts running the periodic callback.\n        \"\"\"\n        if self._cb is not None:\n            raise RuntimeError('Periodic callback has already started.')\n        if not self.running:\n            try:\n                self._updating = True\n                self.running = True\n            finally:\n                self._updating = False\n        self._start_time = time.time()\n        if state.curdoc:\n            self._doc = state.curdoc\n            self._cb = self._doc.add_periodic_callback(self._periodic_callback, self.period)\n        else:\n            from tornado.ioloop import PeriodicCallback\n            self._cb = PeriodicCallback(self._periodic_callback, self.period)\n            self._cb.start()\n        try:\n            state.on_session_destroyed(self._cleanup)\n        except Exception:\n            pass\n\n    def stop(self):\n        \"\"\"\n        Stops running the periodic callback.\n        \"\"\"\n        if self.running:\n            try:\n                self._updating = True\n                self.running = False\n            finally:\n                self._updating = False\n        self._counter = 0\n        self._timeout = None\n        if self._doc:\n            self._doc.remove_periodic_callback(self._cb)\n        else:\n            self._cb.stop()\n        self._cb = None\n        doc = self._doc or _curdoc()\n        if doc:\n            doc.session_destroyed_callbacks = {\n                cb for cb in doc.session_destroyed_callbacks\n                if cb is not self._cleanup\n            }\n            self._doc = None\n", "path": "panel/io/callbacks.py"}], "after_files": [{"content": "\"\"\"\nDefines callbacks to be executed on a thread or by scheduling it\non a running bokeh server.\n\"\"\"\nimport time\nimport param\n\nfrom bokeh.io import curdoc as _curdoc\n\nfrom ..util import edit_readonly\nfrom .state import state\n\n\nclass PeriodicCallback(param.Parameterized):\n    \"\"\"\n    Periodic encapsulates a periodic callback which will run both\n    in tornado based notebook environments and on bokeh server. By\n    default the callback will run until the stop method is called,\n    but count and timeout values can be set to limit the number of\n    executions or the maximum length of time for which the callback\n    will run. The callback may also be started and stopped by setting\n    the running parameter to True or False respectively.\n    \"\"\"\n\n    callback = param.Callable(doc=\"\"\"\n        The callback to execute periodically.\"\"\")\n\n    count = param.Integer(default=None, doc=\"\"\"\n        Number of times the callback will be executed, by default\n        this is unlimited.\"\"\")\n\n    period = param.Integer(default=500, doc=\"\"\"\n        Period in milliseconds at which the callback is executed.\"\"\")\n\n    timeout = param.Integer(default=None, doc=\"\"\"\n        Timeout in milliseconds from the start time at which the callback\n        expires.\"\"\")\n\n    running = param.Boolean(default=False, doc=\"\"\"\n        Toggles whether the periodic callback is currently running.\"\"\")\n\n    def __init__(self, **params):\n        super().__init__(**params)\n        self._counter = 0\n        self._start_time = None\n        self._cb = None\n        self._updating = False\n        self._doc = None\n\n    @param.depends('running', watch=True)\n    def _start(self):\n        if not self.running or self._updating:\n            return\n        self.start()\n\n    @param.depends('running', watch=True)\n    def _stop(self):\n        if self.running or self._updating:\n            return\n        self.stop()\n\n    @param.depends('period', watch=True)\n    def _update_period(self):\n        if self._cb:\n            self.stop()\n            self.start()\n\n    def _periodic_callback(self):\n        with edit_readonly(state):\n            state.busy = True\n        try:\n            self.callback()\n        finally:\n            with edit_readonly(state):\n                state.busy = False\n        self._counter += 1\n        if self.timeout is not None:\n            dt = (time.time() - self._start_time) * 1000\n            if dt > self.timeout:\n                self.stop()\n        if self._counter == self.count:\n            self.stop()\n\n    @property\n    def counter(self):\n        \"\"\"\n        Returns the execution count of the periodic callback.\n        \"\"\"\n        return self._counter\n\n    def _cleanup(self, session_context):\n        self.stop()\n\n    def start(self):\n        \"\"\"\n        Starts running the periodic callback.\n        \"\"\"\n        if self._cb is not None:\n            raise RuntimeError('Periodic callback has already started.')\n        if not self.running:\n            try:\n                self._updating = True\n                self.running = True\n            finally:\n                self._updating = False\n        self._start_time = time.time()\n        if state.curdoc:\n            self._doc = state.curdoc\n            self._cb = self._doc.add_periodic_callback(self._periodic_callback, self.period)\n        else:\n            from tornado.ioloop import PeriodicCallback\n            self._cb = PeriodicCallback(self._periodic_callback, self.period)\n            self._cb.start()\n        try:\n            state.on_session_destroyed(self._cleanup)\n        except Exception:\n            pass\n\n    def stop(self):\n        \"\"\"\n        Stops running the periodic callback.\n        \"\"\"\n        if self.running:\n            try:\n                self._updating = True\n                self.running = False\n            finally:\n                self._updating = False\n        self._counter = 0\n        self._timeout = None\n        if self._doc:\n            self._doc.remove_periodic_callback(self._cb)\n        elif self._cb:\n            self._cb.stop()\n        self._cb = None\n        doc = self._doc or _curdoc()\n        if doc:\n            doc.session_destroyed_callbacks = {\n                cb for cb in doc.session_destroyed_callbacks\n                if cb is not self._cleanup\n            }\n            self._doc = None\n", "path": "panel/io/callbacks.py"}]}