bbot 2.0.1.4720rc0__py3-none-any.whl → 2.3.0.5401rc0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of bbot might be problematic. Click here for more details.
- bbot/__init__.py +1 -1
- bbot/cli.py +3 -7
- bbot/core/config/files.py +0 -1
- bbot/core/config/logger.py +34 -4
- bbot/core/core.py +21 -4
- bbot/core/engine.py +9 -8
- bbot/core/event/base.py +131 -52
- bbot/core/helpers/bloom.py +10 -3
- bbot/core/helpers/command.py +8 -7
- bbot/core/helpers/depsinstaller/installer.py +31 -13
- bbot/core/helpers/diff.py +10 -10
- bbot/core/helpers/dns/brute.py +7 -4
- bbot/core/helpers/dns/dns.py +1 -2
- bbot/core/helpers/dns/engine.py +4 -6
- bbot/core/helpers/dns/helpers.py +2 -2
- bbot/core/helpers/dns/mock.py +0 -1
- bbot/core/helpers/files.py +1 -1
- bbot/core/helpers/helper.py +7 -4
- bbot/core/helpers/interactsh.py +3 -3
- bbot/core/helpers/libmagic.py +65 -0
- bbot/core/helpers/misc.py +65 -22
- bbot/core/helpers/names_generator.py +17 -3
- bbot/core/helpers/process.py +0 -20
- bbot/core/helpers/regex.py +1 -1
- bbot/core/helpers/regexes.py +12 -6
- bbot/core/helpers/validators.py +1 -2
- bbot/core/helpers/web/client.py +1 -1
- bbot/core/helpers/web/engine.py +1 -2
- bbot/core/helpers/web/web.py +4 -114
- bbot/core/helpers/wordcloud.py +5 -5
- bbot/core/modules.py +36 -27
- bbot/core/multiprocess.py +58 -0
- bbot/core/shared_deps.py +46 -3
- bbot/db/sql/models.py +147 -0
- bbot/defaults.yml +12 -10
- bbot/modules/anubisdb.py +2 -2
- bbot/modules/apkpure.py +63 -0
- bbot/modules/azure_tenant.py +2 -2
- bbot/modules/baddns.py +35 -19
- bbot/modules/baddns_direct.py +92 -0
- bbot/modules/baddns_zone.py +3 -8
- bbot/modules/badsecrets.py +4 -3
- bbot/modules/base.py +195 -51
- bbot/modules/bevigil.py +7 -7
- bbot/modules/binaryedge.py +7 -4
- bbot/modules/bufferoverrun.py +47 -0
- bbot/modules/builtwith.py +6 -10
- bbot/modules/bypass403.py +5 -5
- bbot/modules/c99.py +10 -7
- bbot/modules/censys.py +9 -13
- bbot/modules/certspotter.py +5 -3
- bbot/modules/chaos.py +9 -7
- bbot/modules/code_repository.py +1 -0
- bbot/modules/columbus.py +3 -3
- bbot/modules/crt.py +5 -3
- bbot/modules/deadly/dastardly.py +1 -1
- bbot/modules/deadly/ffuf.py +9 -9
- bbot/modules/deadly/nuclei.py +3 -3
- bbot/modules/deadly/vhost.py +4 -3
- bbot/modules/dehashed.py +1 -1
- bbot/modules/digitorus.py +1 -1
- bbot/modules/dnsbimi.py +145 -0
- bbot/modules/dnscaa.py +3 -3
- bbot/modules/dnsdumpster.py +4 -4
- bbot/modules/dnstlsrpt.py +144 -0
- bbot/modules/docker_pull.py +7 -5
- bbot/modules/dockerhub.py +2 -2
- bbot/modules/dotnetnuke.py +20 -21
- bbot/modules/emailformat.py +1 -1
- bbot/modules/extractous.py +122 -0
- bbot/modules/filedownload.py +9 -7
- bbot/modules/fullhunt.py +7 -4
- bbot/modules/generic_ssrf.py +5 -5
- bbot/modules/github_codesearch.py +3 -2
- bbot/modules/github_org.py +4 -4
- bbot/modules/github_workflows.py +4 -4
- bbot/modules/gitlab.py +2 -5
- bbot/modules/google_playstore.py +93 -0
- bbot/modules/gowitness.py +48 -50
- bbot/modules/hackertarget.py +5 -3
- bbot/modules/host_header.py +5 -5
- bbot/modules/httpx.py +1 -4
- bbot/modules/hunterio.py +3 -9
- bbot/modules/iis_shortnames.py +19 -30
- bbot/modules/internal/cloudcheck.py +29 -12
- bbot/modules/internal/dnsresolve.py +22 -22
- bbot/modules/internal/excavate.py +97 -59
- bbot/modules/internal/speculate.py +41 -32
- bbot/modules/internetdb.py +4 -2
- bbot/modules/ip2location.py +3 -5
- bbot/modules/ipneighbor.py +1 -1
- bbot/modules/ipstack.py +3 -8
- bbot/modules/jadx.py +87 -0
- bbot/modules/leakix.py +11 -10
- bbot/modules/myssl.py +2 -2
- bbot/modules/newsletters.py +2 -2
- bbot/modules/otx.py +5 -3
- bbot/modules/output/asset_inventory.py +7 -7
- bbot/modules/output/base.py +1 -1
- bbot/modules/output/csv.py +1 -1
- bbot/modules/output/http.py +20 -14
- bbot/modules/output/mysql.py +51 -0
- bbot/modules/output/neo4j.py +7 -2
- bbot/modules/output/postgres.py +49 -0
- bbot/modules/output/slack.py +0 -1
- bbot/modules/output/sqlite.py +29 -0
- bbot/modules/output/stdout.py +2 -2
- bbot/modules/output/teams.py +107 -6
- bbot/modules/paramminer_headers.py +8 -11
- bbot/modules/passivetotal.py +13 -13
- bbot/modules/portscan.py +32 -6
- bbot/modules/postman.py +50 -126
- bbot/modules/postman_download.py +220 -0
- bbot/modules/rapiddns.py +3 -8
- bbot/modules/report/asn.py +18 -11
- bbot/modules/robots.py +3 -3
- bbot/modules/securitytrails.py +7 -10
- bbot/modules/securitytxt.py +1 -1
- bbot/modules/shodan_dns.py +7 -9
- bbot/modules/sitedossier.py +1 -1
- bbot/modules/skymem.py +2 -2
- bbot/modules/social.py +2 -1
- bbot/modules/subdomaincenter.py +1 -1
- bbot/modules/subdomainradar.py +160 -0
- bbot/modules/telerik.py +8 -8
- bbot/modules/templates/bucket.py +1 -1
- bbot/modules/templates/github.py +22 -14
- bbot/modules/templates/postman.py +21 -0
- bbot/modules/templates/shodan.py +14 -13
- bbot/modules/templates/sql.py +95 -0
- bbot/modules/templates/subdomain_enum.py +51 -16
- bbot/modules/templates/webhook.py +2 -4
- bbot/modules/trickest.py +8 -37
- bbot/modules/trufflehog.py +10 -12
- bbot/modules/url_manipulation.py +3 -3
- bbot/modules/urlscan.py +1 -1
- bbot/modules/viewdns.py +1 -1
- bbot/modules/virustotal.py +8 -30
- bbot/modules/wafw00f.py +1 -1
- bbot/modules/wayback.py +1 -1
- bbot/modules/wpscan.py +17 -11
- bbot/modules/zoomeye.py +11 -6
- bbot/presets/baddns-thorough.yml +12 -0
- bbot/presets/fast.yml +16 -0
- bbot/presets/kitchen-sink.yml +1 -2
- bbot/presets/spider.yml +4 -0
- bbot/presets/subdomain-enum.yml +7 -7
- bbot/presets/web/dotnet-audit.yml +0 -1
- bbot/scanner/manager.py +5 -16
- bbot/scanner/preset/args.py +46 -26
- bbot/scanner/preset/environ.py +7 -2
- bbot/scanner/preset/path.py +7 -4
- bbot/scanner/preset/preset.py +36 -23
- bbot/scanner/scanner.py +172 -62
- bbot/scanner/target.py +236 -434
- bbot/scripts/docs.py +1 -1
- bbot/test/bbot_fixtures.py +13 -3
- bbot/test/conftest.py +132 -100
- bbot/test/fastapi_test.py +17 -0
- bbot/test/owasp_mastg.apk +0 -0
- bbot/test/run_tests.sh +4 -4
- bbot/test/test.conf +2 -0
- bbot/test/test_step_1/test__module__tests.py +0 -1
- bbot/test/test_step_1/test_bbot_fastapi.py +79 -0
- bbot/test/test_step_1/test_bloom_filter.py +2 -1
- bbot/test/test_step_1/test_cli.py +138 -64
- bbot/test/test_step_1/test_dns.py +61 -27
- bbot/test/test_step_1/test_engine.py +17 -19
- bbot/test/test_step_1/test_events.py +183 -30
- bbot/test/test_step_1/test_helpers.py +64 -29
- bbot/test/test_step_1/test_manager_deduplication.py +1 -1
- bbot/test/test_step_1/test_manager_scope_accuracy.py +333 -330
- bbot/test/test_step_1/test_modules_basic.py +68 -70
- bbot/test/test_step_1/test_presets.py +183 -100
- bbot/test/test_step_1/test_python_api.py +7 -2
- bbot/test/test_step_1/test_regexes.py +35 -5
- bbot/test/test_step_1/test_scan.py +39 -5
- bbot/test/test_step_1/test_scope.py +4 -3
- bbot/test/test_step_1/test_target.py +242 -145
- bbot/test/test_step_1/test_web.py +14 -10
- bbot/test/test_step_2/module_tests/base.py +15 -7
- bbot/test/test_step_2/module_tests/test_module_anubisdb.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_apkpure.py +71 -0
- bbot/test/test_step_2/module_tests/test_module_asset_inventory.py +0 -1
- bbot/test/test_step_2/module_tests/test_module_azure_realm.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_baddns.py +6 -6
- bbot/test/test_step_2/module_tests/test_module_baddns_direct.py +62 -0
- bbot/test/test_step_2/module_tests/test_module_bevigil.py +29 -2
- bbot/test/test_step_2/module_tests/test_module_binaryedge.py +4 -2
- bbot/test/test_step_2/module_tests/test_module_bucket_amazon.py +2 -2
- bbot/test/test_step_2/module_tests/test_module_bucket_azure.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_bufferoverrun.py +35 -0
- bbot/test/test_step_2/module_tests/test_module_builtwith.py +2 -2
- bbot/test/test_step_2/module_tests/test_module_bypass403.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_c99.py +126 -0
- bbot/test/test_step_2/module_tests/test_module_censys.py +4 -1
- bbot/test/test_step_2/module_tests/test_module_cloudcheck.py +4 -0
- bbot/test/test_step_2/module_tests/test_module_code_repository.py +11 -1
- bbot/test/test_step_2/module_tests/test_module_columbus.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_credshed.py +3 -3
- bbot/test/test_step_2/module_tests/test_module_dastardly.py +2 -1
- bbot/test/test_step_2/module_tests/test_module_dehashed.py +2 -2
- bbot/test/test_step_2/module_tests/test_module_digitorus.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_discord.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_dnsbimi.py +103 -0
- bbot/test/test_step_2/module_tests/test_module_dnsbrute.py +9 -10
- bbot/test/test_step_2/module_tests/test_module_dnsbrute_mutations.py +1 -2
- bbot/test/test_step_2/module_tests/test_module_dnscommonsrv.py +1 -2
- bbot/test/test_step_2/module_tests/test_module_dnsdumpster.py +4 -4
- bbot/test/test_step_2/module_tests/test_module_dnstlsrpt.py +64 -0
- bbot/test/test_step_2/module_tests/test_module_dotnetnuke.py +0 -8
- bbot/test/test_step_2/module_tests/test_module_excavate.py +28 -48
- bbot/test/test_step_2/module_tests/test_module_extractous.py +54 -0
- bbot/test/test_step_2/module_tests/test_module_ffuf_shortnames.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_filedownload.py +14 -14
- bbot/test/test_step_2/module_tests/test_module_git_clone.py +2 -2
- bbot/test/test_step_2/module_tests/test_module_github_org.py +19 -8
- bbot/test/test_step_2/module_tests/test_module_github_workflows.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_gitlab.py +9 -4
- bbot/test/test_step_2/module_tests/test_module_google_playstore.py +83 -0
- bbot/test/test_step_2/module_tests/test_module_gowitness.py +4 -6
- bbot/test/test_step_2/module_tests/test_module_host_header.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_http.py +4 -4
- bbot/test/test_step_2/module_tests/test_module_httpx.py +10 -8
- bbot/test/test_step_2/module_tests/test_module_hunterio.py +68 -4
- bbot/test/test_step_2/module_tests/test_module_jadx.py +55 -0
- bbot/test/test_step_2/module_tests/test_module_json.py +22 -9
- bbot/test/test_step_2/module_tests/test_module_leakix.py +7 -3
- bbot/test/test_step_2/module_tests/test_module_mysql.py +76 -0
- bbot/test/test_step_2/module_tests/test_module_myssl.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_neo4j.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_newsletters.py +16 -16
- bbot/test/test_step_2/module_tests/test_module_ntlm.py +8 -7
- bbot/test/test_step_2/module_tests/test_module_oauth.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_otx.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_paramminer_cookies.py +1 -2
- bbot/test/test_step_2/module_tests/test_module_paramminer_getparams.py +0 -6
- bbot/test/test_step_2/module_tests/test_module_paramminer_headers.py +2 -9
- bbot/test/test_step_2/module_tests/test_module_passivetotal.py +3 -1
- bbot/test/test_step_2/module_tests/test_module_pgp.py +2 -2
- bbot/test/test_step_2/module_tests/test_module_portscan.py +9 -8
- bbot/test/test_step_2/module_tests/test_module_postgres.py +74 -0
- bbot/test/test_step_2/module_tests/test_module_postman.py +84 -253
- bbot/test/test_step_2/module_tests/test_module_postman_download.py +439 -0
- bbot/test/test_step_2/module_tests/test_module_rapiddns.py +93 -1
- bbot/test/test_step_2/module_tests/test_module_shodan_dns.py +20 -1
- bbot/test/test_step_2/module_tests/test_module_sitedossier.py +2 -2
- bbot/test/test_step_2/module_tests/test_module_smuggler.py +14 -14
- bbot/test/test_step_2/module_tests/test_module_social.py +11 -1
- bbot/test/test_step_2/module_tests/test_module_speculate.py +4 -8
- bbot/test/test_step_2/module_tests/test_module_splunk.py +4 -4
- bbot/test/test_step_2/module_tests/test_module_sqlite.py +18 -0
- bbot/test/test_step_2/module_tests/test_module_sslcert.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_stdout.py +5 -3
- bbot/test/test_step_2/module_tests/test_module_subdomaincenter.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_subdomainradar.py +208 -0
- bbot/test/test_step_2/module_tests/test_module_subdomains.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_teams.py +8 -6
- bbot/test/test_step_2/module_tests/test_module_telerik.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_trufflehog.py +317 -14
- bbot/test/test_step_2/module_tests/test_module_viewdns.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_wayback.py +1 -1
- bbot/test/test_step_2/template_tests/test_template_subdomain_enum.py +2 -2
- bbot/wordlists/devops_mutations.txt +1 -1
- bbot/wordlists/ffuf_shortname_candidates.txt +1 -1
- bbot/wordlists/nameservers.txt +1 -1
- bbot/wordlists/paramminer_headers.txt +1 -1
- bbot/wordlists/paramminer_parameters.txt +1 -1
- bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt +1 -1
- bbot/wordlists/valid_url_schemes.txt +1 -1
- {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/METADATA +48 -18
- bbot-2.3.0.5401rc0.dist-info/RECORD +421 -0
- {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/WHEEL +1 -1
- bbot/modules/unstructured.py +0 -163
- bbot/test/test_step_2/module_tests/test_module_unstructured.py +0 -102
- bbot-2.0.1.4720rc0.dist-info/RECORD +0 -387
- {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/LICENSE +0 -0
- {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/entry_points.txt +0 -0
bbot/__init__.py
CHANGED
bbot/cli.py
CHANGED
|
@@ -29,7 +29,6 @@ scan_name = ""
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
async def _main():
|
|
32
|
-
|
|
33
32
|
import asyncio
|
|
34
33
|
import traceback
|
|
35
34
|
from contextlib import suppress
|
|
@@ -45,7 +44,6 @@ async def _main():
|
|
|
45
44
|
global scan_name
|
|
46
45
|
|
|
47
46
|
try:
|
|
48
|
-
|
|
49
47
|
# start by creating a default scan preset
|
|
50
48
|
preset = Preset(_log=True, name="bbot_cli_main")
|
|
51
49
|
# parse command line arguments and merge into preset
|
|
@@ -81,7 +79,6 @@ async def _main():
|
|
|
81
79
|
|
|
82
80
|
# if we're listing modules or their options
|
|
83
81
|
if options.list_modules or options.list_module_options:
|
|
84
|
-
|
|
85
82
|
# if no modules or flags are specified, enable everything
|
|
86
83
|
if not (options.modules or options.output_modules or options.flags):
|
|
87
84
|
for module, preloaded in preset.module_loader.preloaded().items():
|
|
@@ -133,8 +130,8 @@ async def _main():
|
|
|
133
130
|
]
|
|
134
131
|
if deadly_modules and not options.allow_deadly:
|
|
135
132
|
log.hugewarning(f"You enabled the following deadly modules: {','.join(deadly_modules)}")
|
|
136
|
-
log.hugewarning(
|
|
137
|
-
log.hugewarning(
|
|
133
|
+
log.hugewarning("Deadly modules are highly intrusive")
|
|
134
|
+
log.hugewarning("Please specify --allow-deadly to continue")
|
|
138
135
|
return False
|
|
139
136
|
|
|
140
137
|
# --current-preset
|
|
@@ -172,9 +169,8 @@ async def _main():
|
|
|
172
169
|
log.trace(f"Command: {' '.join(sys.argv)}")
|
|
173
170
|
|
|
174
171
|
if sys.stdin.isatty():
|
|
175
|
-
|
|
176
172
|
# warn if any targets belong directly to a cloud provider
|
|
177
|
-
for event in scan.target.events:
|
|
173
|
+
for event in scan.target.seeds.events:
|
|
178
174
|
if event.type == "DNS_NAME":
|
|
179
175
|
cloudcheck_result = scan.helpers.cloudcheck(event.host)
|
|
180
176
|
if cloudcheck_result:
|
bbot/core/config/files.py
CHANGED
|
@@ -10,7 +10,6 @@ bbot_code_dir = Path(__file__).parent.parent.parent
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class BBOTConfigFiles:
|
|
13
|
-
|
|
14
13
|
config_dir = (Path.home() / ".config" / "bbot").resolve()
|
|
15
14
|
defaults_filename = (bbot_code_dir / "defaults.yml").resolve()
|
|
16
15
|
config_filename = (config_dir / "bbot.yml").resolve()
|
bbot/core/config/logger.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import os
|
|
1
2
|
import sys
|
|
2
3
|
import atexit
|
|
3
4
|
import logging
|
|
@@ -5,9 +6,11 @@ from copy import copy
|
|
|
5
6
|
import multiprocessing
|
|
6
7
|
import logging.handlers
|
|
7
8
|
from pathlib import Path
|
|
9
|
+
from contextlib import suppress
|
|
8
10
|
|
|
9
11
|
from ..helpers.misc import mkdir, error_and_exit
|
|
10
12
|
from ...logger import colorize, loglevel_mapping
|
|
13
|
+
from ..multiprocess import SHARED_INTERPRETER_STATE
|
|
11
14
|
|
|
12
15
|
|
|
13
16
|
debug_format = logging.Formatter("%(asctime)s [%(levelname)s] %(name)s %(filename)s:%(lineno)s %(message)s")
|
|
@@ -64,17 +67,44 @@ class BBOTLogger:
|
|
|
64
67
|
|
|
65
68
|
self.listener = None
|
|
66
69
|
|
|
67
|
-
|
|
68
|
-
if
|
|
70
|
+
# if we haven't set up logging yet, do it now
|
|
71
|
+
if "_BBOT_LOGGING_SETUP" not in os.environ:
|
|
72
|
+
os.environ["_BBOT_LOGGING_SETUP"] = "1"
|
|
69
73
|
self.queue = multiprocessing.Queue()
|
|
70
74
|
self.setup_queue_handler()
|
|
71
75
|
# Start the QueueListener
|
|
72
76
|
self.listener = logging.handlers.QueueListener(self.queue, *self.log_handlers.values())
|
|
73
77
|
self.listener.start()
|
|
74
|
-
atexit.register(self.
|
|
78
|
+
atexit.register(self.cleanup_logging)
|
|
75
79
|
|
|
76
80
|
self.log_level = logging.INFO
|
|
77
81
|
|
|
82
|
+
def cleanup_logging(self):
|
|
83
|
+
# Close the queue handler
|
|
84
|
+
with suppress(Exception):
|
|
85
|
+
self.queue_handler.close()
|
|
86
|
+
|
|
87
|
+
# Clean root logger
|
|
88
|
+
root_logger = logging.getLogger()
|
|
89
|
+
for handler in list(root_logger.handlers):
|
|
90
|
+
with suppress(Exception):
|
|
91
|
+
root_logger.removeHandler(handler)
|
|
92
|
+
with suppress(Exception):
|
|
93
|
+
handler.close()
|
|
94
|
+
|
|
95
|
+
# Clean all other loggers
|
|
96
|
+
for logger in logging.Logger.manager.loggerDict.values():
|
|
97
|
+
if hasattr(logger, "handlers"): # Logger, not PlaceHolder
|
|
98
|
+
for handler in list(logger.handlers):
|
|
99
|
+
with suppress(Exception):
|
|
100
|
+
logger.removeHandler(handler)
|
|
101
|
+
with suppress(Exception):
|
|
102
|
+
handler.close()
|
|
103
|
+
|
|
104
|
+
# Stop queue listener
|
|
105
|
+
with suppress(Exception):
|
|
106
|
+
self.listener.stop()
|
|
107
|
+
|
|
78
108
|
def setup_queue_handler(self, logging_queue=None, log_level=logging.DEBUG):
|
|
79
109
|
if logging_queue is None:
|
|
80
110
|
logging_queue = self.queue
|
|
@@ -86,7 +116,7 @@ class BBOTLogger:
|
|
|
86
116
|
|
|
87
117
|
self.core_logger.setLevel(log_level)
|
|
88
118
|
# disable asyncio logging for child processes
|
|
89
|
-
if
|
|
119
|
+
if not SHARED_INTERPRETER_STATE.is_main_process:
|
|
90
120
|
logging.getLogger("asyncio").setLevel(logging.ERROR)
|
|
91
121
|
|
|
92
122
|
def addLoggingLevel(self, levelName, levelNum, methodName=None):
|
bbot/core/core.py
CHANGED
|
@@ -6,6 +6,7 @@ from contextlib import suppress
|
|
|
6
6
|
from omegaconf import OmegaConf
|
|
7
7
|
|
|
8
8
|
from bbot.errors import BBOTError
|
|
9
|
+
from .multiprocess import SHARED_INTERPRETER_STATE
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
DEFAULT_CONFIG = None
|
|
@@ -41,9 +42,23 @@ class BBOTCore:
|
|
|
41
42
|
self.logger
|
|
42
43
|
self.log = logging.getLogger("bbot.core")
|
|
43
44
|
|
|
45
|
+
self._prep_multiprocessing()
|
|
46
|
+
|
|
47
|
+
def _prep_multiprocessing(self):
|
|
44
48
|
import multiprocessing
|
|
49
|
+
from .helpers.process import BBOTProcess
|
|
50
|
+
|
|
51
|
+
if SHARED_INTERPRETER_STATE.is_main_process:
|
|
52
|
+
# if this is the main bbot process, set the logger and queue for the first time
|
|
53
|
+
from functools import partialmethod
|
|
45
54
|
|
|
46
|
-
|
|
55
|
+
BBOTProcess.__init__ = partialmethod(
|
|
56
|
+
BBOTProcess.__init__, log_level=self.logger.log_level, log_queue=self.logger.queue
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# this makes our process class the default for process pools, etc.
|
|
60
|
+
mp_context = multiprocessing.get_context("spawn")
|
|
61
|
+
mp_context.Process = BBOTProcess
|
|
47
62
|
|
|
48
63
|
@property
|
|
49
64
|
def home(self):
|
|
@@ -91,7 +106,7 @@ class BBOTCore:
|
|
|
91
106
|
if DEFAULT_CONFIG is None:
|
|
92
107
|
self.default_config = self.files_config.get_default_config()
|
|
93
108
|
# ensure bbot home dir
|
|
94
|
-
if
|
|
109
|
+
if "home" not in self.default_config:
|
|
95
110
|
self.default_config["home"] = "~/.bbot"
|
|
96
111
|
return DEFAULT_CONFIG
|
|
97
112
|
|
|
@@ -187,12 +202,14 @@ class BBOTCore:
|
|
|
187
202
|
if os.environ.get("BBOT_TESTING", "") == "True":
|
|
188
203
|
process = self.create_thread(*args, **kwargs)
|
|
189
204
|
else:
|
|
190
|
-
if
|
|
205
|
+
if SHARED_INTERPRETER_STATE.is_scan_process:
|
|
191
206
|
from .helpers.process import BBOTProcess
|
|
192
207
|
|
|
193
208
|
process = BBOTProcess(*args, **kwargs)
|
|
194
209
|
else:
|
|
195
|
-
|
|
210
|
+
import multiprocessing
|
|
211
|
+
|
|
212
|
+
raise BBOTError(f"Tried to start server from process {multiprocessing.current_process().name}")
|
|
196
213
|
process.daemon = True
|
|
197
214
|
return process
|
|
198
215
|
|
bbot/core/engine.py
CHANGED
|
@@ -10,6 +10,7 @@ import traceback
|
|
|
10
10
|
import contextlib
|
|
11
11
|
import contextvars
|
|
12
12
|
import zmq.asyncio
|
|
13
|
+
import multiprocessing
|
|
13
14
|
from pathlib import Path
|
|
14
15
|
from concurrent.futures import CancelledError
|
|
15
16
|
from contextlib import asynccontextmanager, suppress
|
|
@@ -17,6 +18,7 @@ from contextlib import asynccontextmanager, suppress
|
|
|
17
18
|
from bbot.core import CORE
|
|
18
19
|
from bbot.errors import BBOTEngineError
|
|
19
20
|
from bbot.core.helpers.async_helpers import get_event_loop
|
|
21
|
+
from bbot.core.multiprocess import SHARED_INTERPRETER_STATE
|
|
20
22
|
from bbot.core.helpers.misc import rand_string, in_exception_chain
|
|
21
23
|
|
|
22
24
|
|
|
@@ -264,10 +266,8 @@ class EngineClient(EngineBase):
|
|
|
264
266
|
return [s for s in self.CMDS if isinstance(s, str)]
|
|
265
267
|
|
|
266
268
|
def start_server(self):
|
|
267
|
-
import multiprocessing
|
|
268
|
-
|
|
269
269
|
process_name = multiprocessing.current_process().name
|
|
270
|
-
if
|
|
270
|
+
if SHARED_INTERPRETER_STATE.is_scan_process:
|
|
271
271
|
kwargs = dict(self.server_kwargs)
|
|
272
272
|
# if we're in tests, we use a single event loop to avoid weird race conditions
|
|
273
273
|
# this allows us to more easily mock http, etc.
|
|
@@ -641,8 +641,9 @@ class EngineServer(EngineBase):
|
|
|
641
641
|
except BaseException as e:
|
|
642
642
|
if isinstance(e, (TimeoutError, asyncio.exceptions.TimeoutError)):
|
|
643
643
|
self.log.warning(f"{self.name}: Timeout after {timeout:,} seconds in finished_tasks({tasks})")
|
|
644
|
-
for task in tasks:
|
|
644
|
+
for task in list(tasks):
|
|
645
645
|
task.cancel()
|
|
646
|
+
self._await_cancelled_task(task)
|
|
646
647
|
else:
|
|
647
648
|
if not in_exception_chain(e, (KeyboardInterrupt, asyncio.CancelledError)):
|
|
648
649
|
self.log.error(f"{self.name}: Unhandled exception in finished_tasks({tasks}): {e}")
|
|
@@ -664,9 +665,9 @@ class EngineServer(EngineBase):
|
|
|
664
665
|
child_task.cancel()
|
|
665
666
|
|
|
666
667
|
for task in [parent_task] + list(child_tasks):
|
|
667
|
-
await self.
|
|
668
|
+
await self._await_cancelled_task(task)
|
|
668
669
|
|
|
669
|
-
async def
|
|
670
|
+
async def _await_cancelled_task(self, task):
|
|
670
671
|
try:
|
|
671
672
|
await asyncio.wait_for(task, timeout=10)
|
|
672
673
|
except (TimeoutError, asyncio.exceptions.TimeoutError):
|
|
@@ -682,5 +683,5 @@ class EngineServer(EngineBase):
|
|
|
682
683
|
for client_id in list(self.tasks):
|
|
683
684
|
await self.cancel_task(client_id)
|
|
684
685
|
for client_id, tasks in self.child_tasks.items():
|
|
685
|
-
for task in tasks:
|
|
686
|
-
await self.
|
|
686
|
+
for task in list(tasks):
|
|
687
|
+
await self._await_cancelled_task(task)
|