Verify second-block SQL failure and propagate local download errors

This commit is contained in:
evgeny committed 2026-10-22 18:31:12 +02:00
1 parent fd6155aa4a
commit 6a14be05f5
2 files changed
+23 -8

No files matched your search

+8 -3
View File
@@ -230,8 +230,8 @@ static int md_dl_pump(struct media_download* dl) {
if (dl->err) return -1;
for (int bi = 0; bi < dl->num_blocks; bi++) {
struct media_download_block* b = &dl->blocks[bi];
if ((b->state == MD_BLK_IDLE || b->state == MD_BLK_WAIT)
&& md_dl_request_block(dl, bi) < 0 && md_dl_failover_block(dl, bi, get_time_tb()) < 0) return -1;
if (b->state != MD_BLK_IDLE && b->state != MD_BLK_WAIT) continue;
if (md_dl_request_block(dl, bi) < 0 && (dl->err || md_dl_failover_block(dl, bi, get_time_tb()) < 0)) return -1;
}
return 0;
}
@@ -243,10 +243,15 @@ int md_dl_failover_block(struct media_download* dl, int bi, uint64_t now_tb) {
if (md_dl_block_inflight(b) && dl->inflight > 0) dl->inflight--;
b->state = MD_BLK_IDLE; b->bytes_received = 0; b->last_progress_tb = now_tb; b->retry_at_tb = 0;
do {
if (dl->err) return -1;
b->attempts++;
DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "%s: failover block=%d attempts=%d/%d holder=%d/%d",
MDL_ID, bi, b->attempts, md_dl_max_attempts(dl->inst), b->holder_idx, b->num_holders);
if (b->attempts >= md_dl_max_attempts(dl->inst)) { b->state = MD_BLK_FAILED; return -1; }
if (b->attempts >= md_dl_max_attempts(dl->inst)) {
b->state = MD_BLK_FAILED;
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "%s: block attempts exhausted block=%d attempts=%d", MDL_ID, bi, b->attempts);
return -1;
}
if (++b->holder_idx >= b->num_holders) {
b->num_holders = 0; b->holder_idx = -1; b->state = MD_BLK_WAIT; b->wait_reason = MD_WAIT_SEARCH;
return 0;
+15 -5
View File
@@ -7,6 +7,7 @@
#include "../src/media_delivery/media_index.h"
#include "../src/media_delivery/media_download.h"
#include "../src/routing_layer/etcp_router.h"
#include "../src/transport_layer/etcp.h"
#include "../lib/debug_config.h"
#include "../lib/mem.h"
#include "../lib/platform_compat.h"
@@ -53,7 +54,7 @@ int __wrap_etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t group, uint64_t
}
/* u_malloc округляет выделение: ASAN защищает именно логическую границу входного payload. */
static void release_injected(void* data) {
static void release_injected(uint8_t* data) {
#ifdef __SANITIZE_ADDRESS__
if (data == injected) __asan_unpoison_memory_region(poison_tail, 64);
#endif
@@ -263,22 +264,31 @@ static void test_peer_reuse_and_completion(void) {
puts("65 blocks from 13 holders, peer slot reuse, file contents and registration: PASS");
}
static int denied_reads;
static int denied_reads, started_selects;
static int trace_query(unsigned event, void* arg, void* statement, void* sql) {
(void)arg; (void)sql;
if (event == SQLITE_TRACE_STMT && !strncmp(sqlite3_sql(statement), "SELECT node_id FROM (", 21)) started_selects++;
return 0;
}
static int deny_second_block(void* arg, int action, const char* table, const char* column, const char* db, const char* trigger) {
(void)arg; (void)db; (void)trigger;
if (action == SQLITE_READ && table && column && !strcmp(table, "block_availability") && !strcmp(column, "block_uuid"))
if (++denied_reads == 2) return SQLITE_DENY;
if (started_selects) { denied_reads++; return SQLITE_DENY; }
return SQLITE_OK;
}
static void test_failures_and_restart(void) {
reset(); struct UTUN_INSTANCE* s = instance(SERVER); struct UTUN_INSTANCE* c = instance(CLIENT);
struct media_index_result r = result(2); seed(s, &r, 2, 2, 0); start(c, &r);
denied_reads = 0; sqlite3_set_authorizer(s->topo_sqlite_db, deny_second_block, NULL);
denied_reads = started_selects = 0;
sqlite3_trace_v2(s->topo_sqlite_db, SQLITE_TRACE_STMT, trace_query, NULL);
sqlite3_set_authorizer(s->topo_sqlite_db, deny_second_block, NULL);
struct packet error = answer(s);
struct media_pkt_query_resp* header = (struct media_pkt_query_resp*)error.data;
REQUIRE(denied_reads == 2 && header->status == MEDIA_QUERY_DB_ERROR && !header->num_blocks && error.len == MEDIA_QUERY_RESP_HDR_SIZE);
REQUIRE(denied_reads == 1 && started_selects == 1 && header->status == MEDIA_QUERY_DB_ERROR
&& !header->num_blocks && error.len == MEDIA_QUERY_RESP_HDR_SIZE);
sqlite3_set_authorizer(s->topo_sqlite_db, NULL, NULL);
sqlite3_trace_v2(s->topo_sqlite_db, 0, NULL, NULL);
struct media_download* dl = download(c);
REQUIRE(!media_download_cancel(c, dl->media_id, NULL, 0) && done_count == 1);
start(c, &r); dl = download(c); struct media_download snapshot = *dl;