Skip to content

Commit 5fbcbf1

Browse files
authored
Merge pull request #3021 from blacklanternsecurity/blasthttp-integration-sharedloop
blasthttp 0.2.0: shared event loop (eliminate executor bridge)
2 parents 64c1afe + 622088b commit 5fbcbf1

6 files changed

Lines changed: 12 additions & 22 deletions

File tree

bbot/core/helpers/helper.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,8 @@ def loop(self):
208208
"""
209209
if self._loop is None:
210210
self._loop = get_event_loop()
211-
# increase default thread pool size to prevent executor starvation
212-
# during heavy scans where YARA, regex, DNS, and HTTP all compete for threads
213-
thread_pool_size = max(32, (os.cpu_count() or 1) * 4)
214-
self._io_executor = ThreadPoolExecutor(max_workers=thread_pool_size)
211+
# only current caller is wafw00f (sync requests library)
212+
self._io_executor = ThreadPoolExecutor(max_workers=max(8, (os.cpu_count() or 1) + 4))
215213
self._cpu_executor = ThreadPoolExecutor(max_workers=max(8, os.cpu_count() or 4))
216214
self._loop.set_default_executor(self._io_executor)
217215
return self._loop

bbot/core/helpers/web/web.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,8 @@ async def request(self, *args, **kwargs):
266266
if self.http_debug:
267267
log.trace(f"blasthttp request: {method} {url}")
268268

269-
# Run in executor — blasthttp blocks the thread (tokio runtime)
270-
blast_response = await self.parent_helper.run_in_executor_io(self.client.request, url, **blast_kwargs)
269+
# blasthttp returns a native coroutine via pyo3-async-runtimes
270+
blast_response = await self.client.request(url, **blast_kwargs)
271271

272272
response = BlasthttpResponse(blast_response, request_url=url, method=method)
273273

bbot/modules/http.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ async def handle_batch(self, *events):
212212
)
213213
configs.append(config)
214214

215-
# Run batch in executor to avoid blocking the event loop
216-
results = await self.helpers.run_in_executor_io(self.client.request_batch, configs, self.threads)
215+
# blasthttp batch returns a native coroutine via pyo3-async-runtimes
216+
results = await self.client.request_batch(configs, self.threads)
217217

218218
# Index results by URL for the dedup check
219219
results_by_url = {r.url: r for r in results}

bbot/modules/web_brute.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,7 @@ async def baseline_fuzz(self, url, exts=None, prefix="", suffix=""):
180180
)
181181

182182
canary_results = []
183-
results = await self.helpers.run_in_executor_io(
184-
self.blast_client.request_batch, canary_configs, 4, rate_limit=self.rate
185-
)
183+
results = await self.blast_client.request_batch(canary_configs, 4, rate_limit=self.rate)
186184
for result in results:
187185
if result.success:
188186
canary_results.append(self._batch_response_metrics(result.response))
@@ -306,9 +304,7 @@ async def execute_fuzz(
306304
self.debug(f"Fuzzing {len(configs)} URLs for ext [{ext}]")
307305

308306
# Fire all requests via native blasthttp batch (Rust concurrency)
309-
results = await self.helpers.run_in_executor_io(
310-
self.blast_client.request_batch, configs, self.concurrency, rate_limit=self.rate
311-
)
307+
results = await self.blast_client.request_batch(configs, self.concurrency, rate_limit=self.rate)
312308

313309
# Index results by URL for ordered processing
314310
results_by_url = {}
@@ -367,9 +363,7 @@ async def execute_fuzz(
367363
proxy=proxy,
368364
)
369365
]
370-
canary_batch = await self.helpers.run_in_executor_io(
371-
self.blast_client.request_batch, canary_configs, 1, rate_limit=self.rate
372-
)
366+
canary_batch = await self.blast_client.request_batch(canary_configs, 1, rate_limit=self.rate)
373367
if canary_batch and canary_batch[0].success:
374368
canary_metrics = self._batch_response_metrics(canary_batch[0].response)
375369
if not self._is_baseline_match(canary_metrics, ext_filter):

bbot/scanner/scanner.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -768,15 +768,13 @@ def modules_status(self, _log=False, detailed=False):
768768
)
769769

770770
num_queued_events = self.num_queued_events
771-
io_backlog = self.helpers._io_executor._work_queue.qsize()
772-
cpu_backlog = self.helpers._cpu_executor._work_queue.qsize()
773771
if num_queued_events:
774772
self.info(
775-
f"{self.name}: {num_queued_events:,} events in queue ({self.stats.speedometer.speed:,} processed in the past {self.status_frequency} seconds) | Thread pool backlog: I/O: {io_backlog:,}, CPU: {cpu_backlog:,}"
773+
f"{self.name}: {num_queued_events:,} events in queue ({self.stats.speedometer.speed:,} processed in the past {self.status_frequency} seconds)"
776774
)
777775
else:
778776
self.info(
779-
f"{self.name}: No events in queue ({self.stats.speedometer.speed:,} processed in the past {self.status_frequency} seconds) | Thread pool backlog: I/O: {io_backlog:,}, CPU: {cpu_backlog:,}"
777+
f"{self.name}: No events in queue ({self.stats.speedometer.speed:,} processed in the past {self.status_frequency} seconds)"
780778
)
781779

782780
if detailed or self.log_level <= logging.DEBUG:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ dependencies = [
4747
"ansible-core>=2.17,<3",
4848
"tldextract>=5.3.0,<6",
4949
"cloudcheck>=9.2.0,<10",
50-
"blasthttp>=0.1.4",
50+
"blasthttp>=0.2.0",
5151
]
5252

5353
[project.urls]

0 commit comments

Comments
 (0)