We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Connectors should fork
When a connector is started it should fork into its own process. This is because connectors block to accept messages from their source.

This requires #5 to enable persistent memory between connector processes.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `opsdroid/core.py`
Content:
```
1 """Core components of OpsDroid."""
2 
3 import logging
4 import sys
5 import weakref
6 from opsdroid.helper import match
7 from opsdroid.memory import Memory
8 
9 
10 class OpsDroid():
11     """Root object for opsdroid."""
12 
13     instances = []
14 
15     def __init__(self):
16         """Start opsdroid."""
17         self.bot_name = 'opsdroid'
18         self.sys_status = 0
19         self.connectors = []
20         self.skills = []
21         self.memory = Memory()
22         logging.info("Created main opsdroid object")
23 
24     def __enter__(self):
25         """Add self to existing instances."""
26         if len(self.__class__.instances) == 0:
27             self.__class__.instances.append(weakref.proxy(self))
28         else:
29             self.critical("opsdroid has already been started", 1)
30         return self
31 
32     def __exit__(self, exc_type, exc_value, traceback):
33         """Remove self from existing instances."""
34         self.__class__.instances = []
35 
36     def exit(self):
37         """Exit application."""
38         logging.info("Exiting application with return code " +
39                      str(self.sys_status))
40         sys.exit(self.sys_status)
41 
42     def critical(self, error, code):
43         """Exit due to unrecoverable error."""
44         self.sys_status = code
45         logging.critical(error)
46         print("Error: " + error)
47         self.exit()
48 
49     def start_connectors(self, connectors):
50         """Start the connectors."""
51         if len(connectors) == 0:
52             self.critical("All connectors failed to load", 1)
53         for connector_module in connectors:
54             for name, cls in connector_module["module"].__dict__.items():
55                 if isinstance(cls, type) and "Connector" in name:
56                     connector_module["config"]["bot-name"] = self.bot_name
57                     connector = cls(connector_module["config"])
58                     self.connectors.append(connector)
59                     connector.connect(self)
60 
61     def start_databases(self, databases):
62         """Start the databases."""
63         if len(databases) == 0:
64             logging.warning("All databases failed to load")
65         for database_module in databases:
66             for name, cls in database_module["module"].__dict__.items():
67                 if isinstance(cls, type) and "Database" in name:
68                     logging.debug("Adding database: " + name)
69                     database = cls(database_module["config"])
70                     self.memory.databases.append(database)
71                     database.connect()
72 
73     def load_regex_skill(self, regex, skill):
74         """Load skills."""
75         self.skills.append({"regex": regex, "skill": skill})
76 
77     def parse(self, message):
78         """Parse a string against all skills."""
79         if message.text.strip() != "":
80             logging.debug("Parsing input: " + message.text)
81             for skill in self.skills:
82                 if "regex" in skill:
83                     regex = match(skill["regex"], message.text)
84                     if regex:
85                         message.regex = regex
86                         skill["skill"](self, message)
87
```
--- 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/opsdroid/core.py b/opsdroid/core.py
--- a/opsdroid/core.py
+++ b/opsdroid/core.py
@@ -3,6 +3,7 @@
 import logging
 import sys
 import weakref
+from multiprocessing import Process
 from opsdroid.helper import match
 from opsdroid.memory import Memory
 
@@ -17,6 +18,7 @@
         self.bot_name = 'opsdroid'
         self.sys_status = 0
         self.connectors = []
+        self.connector_jobs = []
         self.skills = []
         self.memory = Memory()
         logging.info("Created main opsdroid object")
@@ -56,7 +58,11 @@
                     connector_module["config"]["bot-name"] = self.bot_name
                     connector = cls(connector_module["config"])
                     self.connectors.append(connector)
-                    connector.connect(self)
+                    job = Process(target=connector.connect, args=(self,))
+                    job.start()
+                    self.connector_jobs.append(job)
+        for job in self.connector_jobs:
+            job.join()
 
     def start_databases(self, databases):
         """Start the databases."""

{"golden_diff": "diff --git a/opsdroid/core.py b/opsdroid/core.py\n--- a/opsdroid/core.py\n+++ b/opsdroid/core.py\n@@ -3,6 +3,7 @@\n import logging\n import sys\n import weakref\n+from multiprocessing import Process\n from opsdroid.helper import match\n from opsdroid.memory import Memory\n \n@@ -17,6 +18,7 @@\n         self.bot_name = 'opsdroid'\n         self.sys_status = 0\n         self.connectors = []\n+        self.connector_jobs = []\n         self.skills = []\n         self.memory = Memory()\n         logging.info(\"Created main opsdroid object\")\n@@ -56,7 +58,11 @@\n                     connector_module[\"config\"][\"bot-name\"] = self.bot_name\n                     connector = cls(connector_module[\"config\"])\n                     self.connectors.append(connector)\n-                    connector.connect(self)\n+                    job = Process(target=connector.connect, args=(self,))\n+                    job.start()\n+                    self.connector_jobs.append(job)\n+        for job in self.connector_jobs:\n+            job.join()\n \n     def start_databases(self, databases):\n         \"\"\"Start the databases.\"\"\"\n", "issue": "Connectors should fork\nWhen a connector is started it should fork into its own process. This is because connectors block to accept messages from their source.\n\nThis requires #5 to enable persistent memory between connector processes.\n\n", "before_files": [{"content": "\"\"\"Core components of OpsDroid.\"\"\"\n\nimport logging\nimport sys\nimport weakref\nfrom opsdroid.helper import match\nfrom opsdroid.memory import Memory\n\n\nclass OpsDroid():\n    \"\"\"Root object for opsdroid.\"\"\"\n\n    instances = []\n\n    def __init__(self):\n        \"\"\"Start opsdroid.\"\"\"\n        self.bot_name = 'opsdroid'\n        self.sys_status = 0\n        self.connectors = []\n        self.skills = []\n        self.memory = Memory()\n        logging.info(\"Created main opsdroid object\")\n\n    def __enter__(self):\n        \"\"\"Add self to existing instances.\"\"\"\n        if len(self.__class__.instances) == 0:\n            self.__class__.instances.append(weakref.proxy(self))\n        else:\n            self.critical(\"opsdroid has already been started\", 1)\n        return self\n\n    def __exit__(self, exc_type, exc_value, traceback):\n        \"\"\"Remove self from existing instances.\"\"\"\n        self.__class__.instances = []\n\n    def exit(self):\n        \"\"\"Exit application.\"\"\"\n        logging.info(\"Exiting application with return code \" +\n                     str(self.sys_status))\n        sys.exit(self.sys_status)\n\n    def critical(self, error, code):\n        \"\"\"Exit due to unrecoverable error.\"\"\"\n        self.sys_status = code\n        logging.critical(error)\n        print(\"Error: \" + error)\n        self.exit()\n\n    def start_connectors(self, connectors):\n        \"\"\"Start the connectors.\"\"\"\n        if len(connectors) == 0:\n            self.critical(\"All connectors failed to load\", 1)\n        for connector_module in connectors:\n            for name, cls in connector_module[\"module\"].__dict__.items():\n                if isinstance(cls, type) and \"Connector\" in name:\n                    connector_module[\"config\"][\"bot-name\"] = self.bot_name\n                    connector = cls(connector_module[\"config\"])\n                    self.connectors.append(connector)\n                    connector.connect(self)\n\n    def start_databases(self, databases):\n        \"\"\"Start the databases.\"\"\"\n        if len(databases) == 0:\n            logging.warning(\"All databases failed to load\")\n        for database_module in databases:\n            for name, cls in database_module[\"module\"].__dict__.items():\n                if isinstance(cls, type) and \"Database\" in name:\n                    logging.debug(\"Adding database: \" + name)\n                    database = cls(database_module[\"config\"])\n                    self.memory.databases.append(database)\n                    database.connect()\n\n    def load_regex_skill(self, regex, skill):\n        \"\"\"Load skills.\"\"\"\n        self.skills.append({\"regex\": regex, \"skill\": skill})\n\n    def parse(self, message):\n        \"\"\"Parse a string against all skills.\"\"\"\n        if message.text.strip() != \"\":\n            logging.debug(\"Parsing input: \" + message.text)\n            for skill in self.skills:\n                if \"regex\" in skill:\n                    regex = match(skill[\"regex\"], message.text)\n                    if regex:\n                        message.regex = regex\n                        skill[\"skill\"](self, message)\n", "path": "opsdroid/core.py"}], "after_files": [{"content": "\"\"\"Core components of OpsDroid.\"\"\"\n\nimport logging\nimport sys\nimport weakref\nfrom multiprocessing import Process\nfrom opsdroid.helper import match\nfrom opsdroid.memory import Memory\n\n\nclass OpsDroid():\n    \"\"\"Root object for opsdroid.\"\"\"\n\n    instances = []\n\n    def __init__(self):\n        \"\"\"Start opsdroid.\"\"\"\n        self.bot_name = 'opsdroid'\n        self.sys_status = 0\n        self.connectors = []\n        self.connector_jobs = []\n        self.skills = []\n        self.memory = Memory()\n        logging.info(\"Created main opsdroid object\")\n\n    def __enter__(self):\n        \"\"\"Add self to existing instances.\"\"\"\n        if len(self.__class__.instances) == 0:\n            self.__class__.instances.append(weakref.proxy(self))\n        else:\n            self.critical(\"opsdroid has already been started\", 1)\n        return self\n\n    def __exit__(self, exc_type, exc_value, traceback):\n        \"\"\"Remove self from existing instances.\"\"\"\n        self.__class__.instances = []\n\n    def exit(self):\n        \"\"\"Exit application.\"\"\"\n        logging.info(\"Exiting application with return code \" +\n                     str(self.sys_status))\n        sys.exit(self.sys_status)\n\n    def critical(self, error, code):\n        \"\"\"Exit due to unrecoverable error.\"\"\"\n        self.sys_status = code\n        logging.critical(error)\n        print(\"Error: \" + error)\n        self.exit()\n\n    def start_connectors(self, connectors):\n        \"\"\"Start the connectors.\"\"\"\n        if len(connectors) == 0:\n            self.critical(\"All connectors failed to load\", 1)\n        for connector_module in connectors:\n            for name, cls in connector_module[\"module\"].__dict__.items():\n                if isinstance(cls, type) and \"Connector\" in name:\n                    connector_module[\"config\"][\"bot-name\"] = self.bot_name\n                    connector = cls(connector_module[\"config\"])\n                    self.connectors.append(connector)\n                    job = Process(target=connector.connect, args=(self,))\n                    job.start()\n                    self.connector_jobs.append(job)\n        for job in self.connector_jobs:\n            job.join()\n\n    def start_databases(self, databases):\n        \"\"\"Start the databases.\"\"\"\n        if len(databases) == 0:\n            logging.warning(\"All databases failed to load\")\n        for database_module in databases:\n            for name, cls in database_module[\"module\"].__dict__.items():\n                if isinstance(cls, type) and \"Database\" in name:\n                    logging.debug(\"Adding database: \" + name)\n                    database = cls(database_module[\"config\"])\n                    self.memory.databases.append(database)\n                    database.connect()\n\n    def load_regex_skill(self, regex, skill):\n        \"\"\"Load skills.\"\"\"\n        self.skills.append({\"regex\": regex, \"skill\": skill})\n\n    def parse(self, message):\n        \"\"\"Parse a string against all skills.\"\"\"\n        if message.text.strip() != \"\":\n            logging.debug(\"Parsing input: \" + message.text)\n            for skill in self.skills:\n                if \"regex\" in skill:\n                    regex = match(skill[\"regex\"], message.text)\n                    if regex:\n                        message.regex = regex\n                        skill[\"skill\"](self, message)\n", "path": "opsdroid/core.py"}]}