We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
notebook.start_kernel is undefined
Hi, in notificationarea.js, when we need to restart a kernel we call `notebook.start_kernel` which doesn't exist.  Not sure how you guys were planning to handle this, but I took a stab at it.

thanks!


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `IPython/html/services/sessions/handlers.py`
Content:
```
1 """Tornado handlers for the sessions web service."""
2 
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5 
6 import json
7 
8 from tornado import web
9 
10 from ...base.handlers import IPythonHandler, json_errors
11 from IPython.utils.jsonutil import date_default
12 from IPython.html.utils import url_path_join, url_escape
13 from IPython.kernel.kernelspec import NoSuchKernel
14 
15 
16 class SessionRootHandler(IPythonHandler):
17 
18     @web.authenticated
19     @json_errors
20     def get(self):
21         # Return a list of running sessions
22         sm = self.session_manager
23         sessions = sm.list_sessions()
24         self.finish(json.dumps(sessions, default=date_default))
25 
26     @web.authenticated
27     @json_errors
28     def post(self):
29         # Creates a new session
30         #(unless a session already exists for the named nb)
31         sm = self.session_manager
32         cm = self.contents_manager
33         km = self.kernel_manager
34 
35         model = self.get_json_body()
36         if model is None:
37             raise web.HTTPError(400, "No JSON data provided")
38         try:
39             name = model['notebook']['name']
40         except KeyError:
41             raise web.HTTPError(400, "Missing field in JSON data: notebook.name")
42         try:
43             path = model['notebook']['path']
44         except KeyError:
45             raise web.HTTPError(400, "Missing field in JSON data: notebook.path")
46         try:
47             kernel_name = model['kernel']['name']
48         except KeyError:
49             self.log.debug("No kernel name specified, using default kernel")
50             kernel_name = None
51 
52         # Check to see if session exists
53         if sm.session_exists(name=name, path=path):
54             model = sm.get_session(name=name, path=path)
55         else:
56             try:
57                 model = sm.create_session(name=name, path=path, kernel_name=kernel_name)
58             except NoSuchKernel:
59                 msg = ("The '%s' kernel is not available. Please pick another "
60                        "suitable kernel instead, or install that kernel." % kernel_name)
61                 status_msg = '%s not found' % kernel_name
62                 self.log.warn('Kernel not found: %s' % kernel_name)
63                 self.set_status(501)
64                 self.finish(json.dumps(dict(message=msg, short_message=status_msg)))
65                 return
66 
67         location = url_path_join(self.base_url, 'api', 'sessions', model['id'])
68         self.set_header('Location', url_escape(location))
69         self.set_status(201)
70         self.finish(json.dumps(model, default=date_default))
71 
72 class SessionHandler(IPythonHandler):
73 
74     SUPPORTED_METHODS = ('GET', 'PATCH', 'DELETE')
75 
76     @web.authenticated
77     @json_errors
78     def get(self, session_id):
79         # Returns the JSON model for a single session
80         sm = self.session_manager
81         model = sm.get_session(session_id=session_id)
82         self.finish(json.dumps(model, default=date_default))
83 
84     @web.authenticated
85     @json_errors
86     def patch(self, session_id):
87         # Currently, this handler is strictly for renaming notebooks
88         sm = self.session_manager
89         model = self.get_json_body()
90         if model is None:
91             raise web.HTTPError(400, "No JSON data provided")
92         changes = {}
93         if 'notebook' in model:
94             notebook = model['notebook']
95             if 'name' in notebook:
96                 changes['name'] = notebook['name']
97             if 'path' in notebook:
98                 changes['path'] = notebook['path']
99 
100         sm.update_session(session_id, **changes)
101         model = sm.get_session(session_id=session_id)
102         self.finish(json.dumps(model, default=date_default))
103 
104     @web.authenticated
105     @json_errors
106     def delete(self, session_id):
107         # Deletes the session with given session_id
108         sm = self.session_manager
109         sm.delete_session(session_id)
110         self.set_status(204)
111         self.finish()
112 
113 
114 #-----------------------------------------------------------------------------
115 # URL to handler mappings
116 #-----------------------------------------------------------------------------
117 
118 _session_id_regex = r"(?P<session_id>\w+-\w+-\w+-\w+-\w+)"
119 
120 default_handlers = [
121     (r"/api/sessions/%s" % _session_id_regex, SessionHandler),
122     (r"/api/sessions",  SessionRootHandler)
123 ]
124 
125
```
--- 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/IPython/html/services/sessions/handlers.py b/IPython/html/services/sessions/handlers.py
--- a/IPython/html/services/sessions/handlers.py
+++ b/IPython/html/services/sessions/handlers.py
@@ -106,7 +106,11 @@
     def delete(self, session_id):
         # Deletes the session with given session_id
         sm = self.session_manager
-        sm.delete_session(session_id)
+        try:
+            sm.delete_session(session_id)
+        except KeyError:
+            # the kernel was deleted but the session wasn't!
+            raise web.HTTPError(410, "Kernel deleted before session")
         self.set_status(204)
         self.finish()

{"golden_diff": "diff --git a/IPython/html/services/sessions/handlers.py b/IPython/html/services/sessions/handlers.py\n--- a/IPython/html/services/sessions/handlers.py\n+++ b/IPython/html/services/sessions/handlers.py\n@@ -106,7 +106,11 @@\n     def delete(self, session_id):\n         # Deletes the session with given session_id\n         sm = self.session_manager\n-        sm.delete_session(session_id)\n+        try:\n+            sm.delete_session(session_id)\n+        except KeyError:\n+            # the kernel was deleted but the session wasn't!\n+            raise web.HTTPError(410, \"Kernel deleted before session\")\n         self.set_status(204)\n         self.finish()\n", "issue": "notebook.start_kernel is undefined\nHi, in notificationarea.js, when we need to restart a kernel we call `notebook.start_kernel` which doesn't exist.  Not sure how you guys were planning to handle this, but I took a stab at it.\n\nthanks!\n\n", "before_files": [{"content": "\"\"\"Tornado handlers for the sessions web service.\"\"\"\n\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport json\n\nfrom tornado import web\n\nfrom ...base.handlers import IPythonHandler, json_errors\nfrom IPython.utils.jsonutil import date_default\nfrom IPython.html.utils import url_path_join, url_escape\nfrom IPython.kernel.kernelspec import NoSuchKernel\n\n\nclass SessionRootHandler(IPythonHandler):\n\n    @web.authenticated\n    @json_errors\n    def get(self):\n        # Return a list of running sessions\n        sm = self.session_manager\n        sessions = sm.list_sessions()\n        self.finish(json.dumps(sessions, default=date_default))\n\n    @web.authenticated\n    @json_errors\n    def post(self):\n        # Creates a new session\n        #(unless a session already exists for the named nb)\n        sm = self.session_manager\n        cm = self.contents_manager\n        km = self.kernel_manager\n\n        model = self.get_json_body()\n        if model is None:\n            raise web.HTTPError(400, \"No JSON data provided\")\n        try:\n            name = model['notebook']['name']\n        except KeyError:\n            raise web.HTTPError(400, \"Missing field in JSON data: notebook.name\")\n        try:\n            path = model['notebook']['path']\n        except KeyError:\n            raise web.HTTPError(400, \"Missing field in JSON data: notebook.path\")\n        try:\n            kernel_name = model['kernel']['name']\n        except KeyError:\n            self.log.debug(\"No kernel name specified, using default kernel\")\n            kernel_name = None\n\n        # Check to see if session exists\n        if sm.session_exists(name=name, path=path):\n            model = sm.get_session(name=name, path=path)\n        else:\n            try:\n                model = sm.create_session(name=name, path=path, kernel_name=kernel_name)\n            except NoSuchKernel:\n                msg = (\"The '%s' kernel is not available. Please pick another \"\n                       \"suitable kernel instead, or install that kernel.\" % kernel_name)\n                status_msg = '%s not found' % kernel_name\n                self.log.warn('Kernel not found: %s' % kernel_name)\n                self.set_status(501)\n                self.finish(json.dumps(dict(message=msg, short_message=status_msg)))\n                return\n\n        location = url_path_join(self.base_url, 'api', 'sessions', model['id'])\n        self.set_header('Location', url_escape(location))\n        self.set_status(201)\n        self.finish(json.dumps(model, default=date_default))\n\nclass SessionHandler(IPythonHandler):\n\n    SUPPORTED_METHODS = ('GET', 'PATCH', 'DELETE')\n\n    @web.authenticated\n    @json_errors\n    def get(self, session_id):\n        # Returns the JSON model for a single session\n        sm = self.session_manager\n        model = sm.get_session(session_id=session_id)\n        self.finish(json.dumps(model, default=date_default))\n\n    @web.authenticated\n    @json_errors\n    def patch(self, session_id):\n        # Currently, this handler is strictly for renaming notebooks\n        sm = self.session_manager\n        model = self.get_json_body()\n        if model is None:\n            raise web.HTTPError(400, \"No JSON data provided\")\n        changes = {}\n        if 'notebook' in model:\n            notebook = model['notebook']\n            if 'name' in notebook:\n                changes['name'] = notebook['name']\n            if 'path' in notebook:\n                changes['path'] = notebook['path']\n\n        sm.update_session(session_id, **changes)\n        model = sm.get_session(session_id=session_id)\n        self.finish(json.dumps(model, default=date_default))\n\n    @web.authenticated\n    @json_errors\n    def delete(self, session_id):\n        # Deletes the session with given session_id\n        sm = self.session_manager\n        sm.delete_session(session_id)\n        self.set_status(204)\n        self.finish()\n\n\n#-----------------------------------------------------------------------------\n# URL to handler mappings\n#-----------------------------------------------------------------------------\n\n_session_id_regex = r\"(?P<session_id>\\w+-\\w+-\\w+-\\w+-\\w+)\"\n\ndefault_handlers = [\n    (r\"/api/sessions/%s\" % _session_id_regex, SessionHandler),\n    (r\"/api/sessions\",  SessionRootHandler)\n]\n\n", "path": "IPython/html/services/sessions/handlers.py"}], "after_files": [{"content": "\"\"\"Tornado handlers for the sessions web service.\"\"\"\n\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport json\n\nfrom tornado import web\n\nfrom ...base.handlers import IPythonHandler, json_errors\nfrom IPython.utils.jsonutil import date_default\nfrom IPython.html.utils import url_path_join, url_escape\nfrom IPython.kernel.kernelspec import NoSuchKernel\n\n\nclass SessionRootHandler(IPythonHandler):\n\n    @web.authenticated\n    @json_errors\n    def get(self):\n        # Return a list of running sessions\n        sm = self.session_manager\n        sessions = sm.list_sessions()\n        self.finish(json.dumps(sessions, default=date_default))\n\n    @web.authenticated\n    @json_errors\n    def post(self):\n        # Creates a new session\n        #(unless a session already exists for the named nb)\n        sm = self.session_manager\n        cm = self.contents_manager\n        km = self.kernel_manager\n\n        model = self.get_json_body()\n        if model is None:\n            raise web.HTTPError(400, \"No JSON data provided\")\n        try:\n            name = model['notebook']['name']\n        except KeyError:\n            raise web.HTTPError(400, \"Missing field in JSON data: notebook.name\")\n        try:\n            path = model['notebook']['path']\n        except KeyError:\n            raise web.HTTPError(400, \"Missing field in JSON data: notebook.path\")\n        try:\n            kernel_name = model['kernel']['name']\n        except KeyError:\n            self.log.debug(\"No kernel name specified, using default kernel\")\n            kernel_name = None\n\n        # Check to see if session exists\n        if sm.session_exists(name=name, path=path):\n            model = sm.get_session(name=name, path=path)\n        else:\n            try:\n                model = sm.create_session(name=name, path=path, kernel_name=kernel_name)\n            except NoSuchKernel:\n                msg = (\"The '%s' kernel is not available. Please pick another \"\n                       \"suitable kernel instead, or install that kernel.\" % kernel_name)\n                status_msg = '%s not found' % kernel_name\n                self.log.warn('Kernel not found: %s' % kernel_name)\n                self.set_status(501)\n                self.finish(json.dumps(dict(message=msg, short_message=status_msg)))\n                return\n\n        location = url_path_join(self.base_url, 'api', 'sessions', model['id'])\n        self.set_header('Location', url_escape(location))\n        self.set_status(201)\n        self.finish(json.dumps(model, default=date_default))\n\nclass SessionHandler(IPythonHandler):\n\n    SUPPORTED_METHODS = ('GET', 'PATCH', 'DELETE')\n\n    @web.authenticated\n    @json_errors\n    def get(self, session_id):\n        # Returns the JSON model for a single session\n        sm = self.session_manager\n        model = sm.get_session(session_id=session_id)\n        self.finish(json.dumps(model, default=date_default))\n\n    @web.authenticated\n    @json_errors\n    def patch(self, session_id):\n        # Currently, this handler is strictly for renaming notebooks\n        sm = self.session_manager\n        model = self.get_json_body()\n        if model is None:\n            raise web.HTTPError(400, \"No JSON data provided\")\n        changes = {}\n        if 'notebook' in model:\n            notebook = model['notebook']\n            if 'name' in notebook:\n                changes['name'] = notebook['name']\n            if 'path' in notebook:\n                changes['path'] = notebook['path']\n\n        sm.update_session(session_id, **changes)\n        model = sm.get_session(session_id=session_id)\n        self.finish(json.dumps(model, default=date_default))\n\n    @web.authenticated\n    @json_errors\n    def delete(self, session_id):\n        # Deletes the session with given session_id\n        sm = self.session_manager\n        try:\n            sm.delete_session(session_id)\n        except KeyError:\n            # the kernel was deleted but the session wasn't!\n            raise web.HTTPError(410, \"Kernel deleted before session\")\n        self.set_status(204)\n        self.finish()\n\n\n#-----------------------------------------------------------------------------\n# URL to handler mappings\n#-----------------------------------------------------------------------------\n\n_session_id_regex = r\"(?P<session_id>\\w+-\\w+-\\w+-\\w+-\\w+)\"\n\ndefault_handlers = [\n    (r\"/api/sessions/%s\" % _session_id_regex, SessionHandler),\n    (r\"/api/sessions\",  SessionRootHandler)\n]\n\n", "path": "IPython/html/services/sessions/handlers.py"}]}