task: metadata: install: pip install -e .[dev]
patch: diff --git a/sanic/asgi.py b/sanic/asgi.py
index c3d669e7..d8ab4cfa 100644
--- a/sanic/asgi.py
+++ b/sanic/asgi.py
@@ -9,7 +9,7 @@ from sanic.compat import Header
 from sanic.exceptions import ServerError
 from sanic.helpers import Default
 from sanic.http import Stage
-from sanic.log import logger
+from sanic.log import error_logger, logger
 from sanic.models.asgi import ASGIReceive, ASGIScope, ASGISend, MockTransport
 from sanic.request import Request
 from sanic.response import BaseHTTPResponse
@@ -85,13 +85,27 @@ class Lifespan:
     ) -> None:
         message = await receive()
         if message["type"] == "lifespan.startup":
-            await self.startup()
-            await send({"type": "lifespan.startup.complete"})
+            try:
+                await self.startup()
+            except Exception as e:
+                error_logger.exception(e)
+                await send(
+                    {"type": "lifespan.startup.failed", "message": str(e)}
+                )
+            else:
+                await send({"type": "lifespan.startup.complete"})
 
         message = await receive()
         if message["type"] == "lifespan.shutdown":
-            await self.shutdown()
-            await send({"type": "lifespan.shutdown.complete"})
+            try:
+                await self.shutdown()
+            except Exception as e:
+                error_logger.exception(e)
+                await send(
+                    {"type": "lifespan.shutdown.failed", "message": str(e)}
+                )
+            else:
+                await send({"type": "lifespan.shutdown.complete"})
 
 
 class ASGIApp:

problem_statement: Uvicorn ignores listeners errors
**Describe the bug**
When an exception happens on a listener the error is not reported and the server doesn't crash when using Uvicorn.


**Code snippet**
```python
from sanic import Sanic
from sanic.response import text

app = Sanic("MyHelloWorldApp")

@app.listener("before_server_start")
async def raises(app, loop):
    print("Trying to run faster")
    raise Exception("oh noes")

@app.get("/")
async def hello_world(request):
    return text("Hello, world.")
```

```
~ uvicorn app:app
INFO:     Started server process [49837]
INFO:     Waiting for application startup.
[2022-01-25 14:57:34 +0100] [49837] [INFO]
  ┌────────────────────────────────────────────────────────────────┐
  │                         Sanic v21.12.1                         │
  │                                                                │
  ├───────────────────────┬────────────────────────────────────────┤
  │                       │     mode: production, ASGI             │
  │     ▄███ █████ ██     │   server: sanic                        │
  │    ██                 │   python: 3.9.10                       │
  │     ▀███████ ███▄     │ platform: macOS-12.1-x86_64-i386-64bit │
  │                 ██    │ packages: sanic-routing==0.7.2         │
  │    ████ ████████▀     │                                        │
  │                       │                                        │
  │ Build Fast. Run Fast. │                                        │
  └───────────────────────┴────────────────────────────────────────┘

/Users/andre.ericson/projects/sanic-uvicorn/.venv/lib/python3.9/site-packages/sanic/asgi.py:27: UserWarning: You have set a listener for "before_server_start" in ASGI mode. It will be executed as early as possible, but not before the ASGI server is started.
  warnings.warn(
Trying to run faster
INFO:     ASGI 'lifespan' protocol appears unsupported.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
``` 
**Expected behavior**
The server should crash, or at least log an error.


**Environment (please complete the following information):**
 - MacOS
 - python 3.9.10
 ```
 pip list
Package       Version
------------- ------------
aiofiles      0.8.0
asgiref       3.5.0
click         8.0.3
h11           0.13.0
httptools     0.3.0
multidict     5.2.0
pip           21.3.1
sanic         21.12.1
sanic-routing 0.7.2
setuptools    58.1.0
ujson         5.1.0
uvicorn       0.17.0.post1
uvloop        0.16.0
websockets    10.1
 ```


**Additional context**
Works as expected with `sanic app.app` and also with GunicornWorker.
repo: sanic-org/sanic
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_asgi.py b/tests/test_asgi.py
index e612e3fe..0c76a67f 100644
--- a/tests/test_asgi.py
+++ b/tests/test_asgi.py
@@ -8,7 +8,7 @@ import uvicorn
 
 from sanic import Sanic
 from sanic.application.state import Mode
-from sanic.asgi import MockTransport
+from sanic.asgi import ASGIApp, MockTransport
 from sanic.exceptions import BadRequest, Forbidden, ServiceUnavailable
 from sanic.request import Request
 from sanic.response import json, text
@@ -16,6 +16,12 @@ from sanic.server.websockets.connection import WebSocketConnection
 from sanic.signals import RESERVED_NAMESPACES
 
 
+try:
+    from unittest.mock import AsyncMock
+except ImportError:
+    from tests.asyncmock import AsyncMock  # type: ignore
+
+
 @pytest.fixture
 def message_stack():
     return deque()
@@ -558,3 +564,39 @@ async def test_asgi_serve_location(app):
 
     _, response = await app.asgi_client.get("/")
     assert response.text == "http://<ASGI>"
+
+
+@pytest.mark.asyncio
+async def test_error_on_lifespan_exception_start(app, caplog):
+    @app.before_server_start
+    async def before_server_start(_):
+        1 / 0
+
+    recv = AsyncMock(return_value={"type": "lifespan.startup"})
+    send = AsyncMock()
+    app.asgi = True
+
+    with caplog.at_level(logging.ERROR):
+        await ASGIApp.create(app, {"type": "lifespan"}, recv, send)
+
+    send.assert_awaited_once_with(
+        {"type": "lifespan.startup.failed", "message": "division by zero"}
+    )
+
+
+@pytest.mark.asyncio
+async def test_error_on_lifespan_exception_stop(app: Sanic):
+    @app.before_server_stop
+    async def before_server_stop(_):
+        1 / 0
+
+    recv = AsyncMock(return_value={"type": "lifespan.shutdown"})
+    send = AsyncMock()
+    app.asgi = True
+    await app._startup()
+
+    await ASGIApp.create(app, {"type": "lifespan"}, recv, send)
+
+    send.assert_awaited_once_with(
+        {"type": "lifespan.shutdown.failed", "message": "division by zero"}
+    )