Skip to content

Commit f138d8d

Browse files
authored
Break-glass merge PR #2617
2 parents 56700bd + 2317c2e commit f138d8d

2 files changed

Lines changed: 42 additions & 19 deletions

File tree

‎src/pipeline/pass_k8s.c‎

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,15 @@ static void k8s_kusts_free(k8s_kusts_t *ks) {
760760
*ks = (k8s_kusts_t){0};
761761
}
762762

763+
/* qsort for this file's vectors. An empty vector's items is NULL, and glibc
764+
* declares qsort's base nonnull, so sorting it is undefined even with n == 0
765+
* (UBSan nonnull-attribute on Linux). Fewer than two elements need no sort. */
766+
static void k8s_qsort(void *base, size_t n, size_t size, int (*cmp)(const void *, const void *)) {
767+
if (base && n > 1) {
768+
qsort(base, n, size, cmp);
769+
}
770+
}
771+
763772
static int k8s_cmp_str(const void *a, const void *b) {
764773
return strcmp(*(const char *const *)a, *(const char *const *)b);
765774
}
@@ -827,9 +836,9 @@ static void k8s_kusts_wire(cbm_pipeline_ctx_t *ctx, k8s_kusts_t *ks, CBMHashTabl
827836
}
828837
}
829838
for (int i = 0; i < ks->count; i++) {
830-
qsort(ks->items[i].files, (size_t)ks->items[i].file_n, sizeof(*ks->items[i].files),
831-
k8s_cmp_str);
832-
qsort(ks->items[i].kids, (size_t)ks->items[i].kid_n, sizeof(int), k8s_cmp_int);
839+
k8s_qsort(ks->items[i].files, (size_t)ks->items[i].file_n, sizeof(*ks->items[i].files),
840+
k8s_cmp_str);
841+
k8s_qsort(ks->items[i].kids, (size_t)ks->items[i].kid_n, sizeof(int), k8s_cmp_int);
833842
}
834843
}
835844

@@ -1006,7 +1015,7 @@ static void k8s_bundles_build(cbm_pipeline_ctx_t *ctx, k8s_kusts_t *ks, k8s_bund
10061015
if (!b->names || !b->members || !b->charts) {
10071016
return;
10081017
}
1009-
qsort(ks->items, (size_t)ks->count, sizeof(*ks->items), k8s_cmp_kust);
1018+
k8s_qsort(ks->items, (size_t)ks->count, sizeof(*ks->items), k8s_cmp_kust);
10101019
CBMHashTable *by_path = cbm_ht_create(0);
10111020
if (!by_path) {
10121021
return;
@@ -1345,7 +1354,7 @@ static void k8s_paths_sort_unique(k8s_paths_t *v) {
13451354
if (v->count == 0) {
13461355
return;
13471356
}
1348-
qsort((void *)v->items, (size_t)v->count, sizeof(*v->items), k8s_cmp_str);
1357+
k8s_qsort((void *)v->items, (size_t)v->count, sizeof(*v->items), k8s_cmp_str);
13491358
int w = SKIP_ONE;
13501359
for (int i = SKIP_ONE; i < v->count; i++) {
13511360
if (strcmp(v->items[w - SKIP_ONE], v->items[i]) != 0) {
@@ -1522,7 +1531,7 @@ static void k8s_deploys_build(cbm_pipeline_ctx_t *ctx, k8s_kusts_t *ks, k8s_bund
15221531
k8s_dir_members(ks, by_path, &manifests, f->deploys[d].dir, seen, d + SKIP_ONE,
15231532
&members[d], NULL);
15241533
}
1525-
qsort(keys, un, sizeof(*keys), k8s_cmp_deploy_key);
1534+
k8s_qsort(keys, un, sizeof(*keys), k8s_cmp_deploy_key);
15261535
/* deploy d reaches deploy e when e sits in a manifest d applies */
15271536
for (int d = 0; d < n; d++) {
15281537
for (int i = 0; i < members[d].count; i++) {
@@ -1626,7 +1635,7 @@ static void k8s_ids_sort_unique(k8s_ids_t *v) {
16261635
if (v->count < PAIR_LEN) {
16271636
return;
16281637
}
1629-
qsort(v->items, (size_t)v->count, sizeof(*v->items), k8s_cmp_id);
1638+
k8s_qsort(v->items, (size_t)v->count, sizeof(*v->items), k8s_cmp_id);
16301639
int w = SKIP_ONE;
16311640
for (int i = SKIP_ONE; i < v->count; i++) {
16321641
if (v->items[i] != v->items[w - SKIP_ONE]) {
@@ -1974,7 +1983,7 @@ static void k8s_link_crds(cbm_pipeline_ctx_t *ctx, k8s_bundles_t *b, const k8s_f
19741983
snprintf(order[i].key, sizeof(order[i].key), "%s/%s", f->crds[i].group, f->crds[i].kind);
19751984
order[i].crd = i;
19761985
}
1977-
qsort(order, (size_t)f->crd_n, sizeof(*order), k8s_cmp_crd_key);
1986+
k8s_qsort(order, (size_t)f->crd_n, sizeof(*order), k8s_cmp_crd_key);
19781987
for (int i = f->crd_n - SKIP_ONE; i >= 0; i--) {
19791988
cbm_ht_set(by_type, order[i].key, (void *)(intptr_t)(i + SKIP_ONE)); /* first of run */
19801989
}
@@ -2128,7 +2137,7 @@ static int k8s_cmp_match(const void *a, const void *b) {
21282137
* there is one, is the one it selects. */
21292138
static int k8s_draw_matches(cbm_pipeline_ctx_t *ctx, const k8s_record_array_t *recs,
21302139
const k8s_record_t *svc, k8s_match_t *m, int n) {
2131-
qsort(m, (size_t)n, sizeof(*m), k8s_cmp_match);
2140+
k8s_qsort(m, (size_t)n, sizeof(*m), k8s_cmp_match);
21322141
int edges = 0;
21332142
for (int g = 0; g < n;) {
21342143
int end = g;

‎tests/test_pipeline.c‎

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3524,11 +3524,18 @@ TEST(incremental_shell_deploy_edit_keeps_its_edges) {
35243524

35253525
/* Deleting the only file that starts a program leaves no Process node
35263526
* behind -- a full index never makes one without a SPAWNS edge. One script
3527-
* (pass_shell.c) and one Python call (pass_spawns.c) go; the program a kept
3528-
* script starts stays. `legacy`: through the full-load route, else the
3529-
* closure-repair route. Returns the Process count after the deletion, or -1;
3530-
* *route: the route taken. */
3531-
static int incremental_spawner_delete(bool legacy, cbm_incremental_route_t *route) {
3527+
* (pass_shell.c) and one Python call (pass_spawns.c) start programs; the
3528+
* program a kept script starts stays.
3529+
* - `legacy`: both go at once, through the full-load route.
3530+
* - otherwise in two steps: the script alone goes through closure repair,
3531+
* then the Python file, whose deletion the Python namespace admission
3532+
* declines (a deleted module's names leave its importers' namespaces), so
3533+
* it takes the full route.
3534+
* Returns the Process count after the last deletion, or -1. *route: the route
3535+
* of the first (or only) step; *after_script and *python_route: the count and
3536+
* the route after the script-only step and the Python step (two-step mode). */
3537+
static int incremental_spawner_delete(bool legacy, cbm_incremental_route_t *route,
3538+
int *after_script, cbm_incremental_route_t *python_route) {
35323539
char tmp[256];
35333540
snprintf(tmp, sizeof(tmp), "/tmp/cbm_spawngc_XXXXXX");
35343541
if (!cbm_mkdtemp(tmp)) {
@@ -3545,28 +3552,35 @@ static int incremental_spawner_delete(bool legacy, cbm_incremental_route_t *rout
35453552
char path[512];
35463553
snprintf(path, sizeof(path), "%s/hack/a.sh", tmp);
35473554
(void)remove(path);
3555+
if (!legacy) {
3556+
*after_script =
3557+
k8s_inc_index(tmp, db_path) == 0 ? k8s_inc_count(db_path, processes) : -1;
3558+
*route = cbm_pipeline_incremental_test_last_route();
3559+
}
35483560
snprintf(path, sizeof(path), "%s/app.py", tmp);
35493561
(void)remove(path);
35503562
#if defined(CBM_INCREMENTAL_TEST_API) && CBM_INCREMENTAL_TEST_API
35513563
if (legacy) {
35523564
cbm_pipeline_incremental_test_force_legacy_partial_once();
35533565
}
3554-
#else
3555-
(void)legacy;
35563566
#endif
35573567
int after = k8s_inc_index(tmp, db_path) == 0 ? k8s_inc_count(db_path, processes) : -1;
3558-
*route = cbm_pipeline_incremental_test_last_route();
3568+
*(legacy ? route : python_route) = cbm_pipeline_incremental_test_last_route();
35593569
th_rmtree(tmp);
35603570
return full == 3 ? after : -1;
35613571
}
35623572

35633573
TEST(incremental_deleted_spawner_drops_its_process) {
35643574
cbm_incremental_route_t route = CBM_INCREMENTAL_ROUTE_NONE;
3565-
int left = incremental_spawner_delete(false, &route);
3575+
cbm_incremental_route_t python_route = CBM_INCREMENTAL_ROUTE_NONE;
3576+
int after_script = -1;
3577+
int left = incremental_spawner_delete(false, &route, &after_script, &python_route);
35663578
ASSERT_EQ(route, CBM_INCREMENTAL_ROUTE_CLOSURE_REPAIR);
3579+
ASSERT_EQ(after_script, 2); /* tool-a gone; tool-b and tool-c stay */
3580+
ASSERT_EQ(python_route, CBM_INCREMENTAL_ROUTE_FORCED_FULL);
35673581
ASSERT_EQ(left, 1);
35683582
#if defined(CBM_INCREMENTAL_TEST_API) && CBM_INCREMENTAL_TEST_API
3569-
left = incremental_spawner_delete(true, &route);
3583+
left = incremental_spawner_delete(true, &route, &after_script, &python_route);
35703584
ASSERT_EQ(route, CBM_INCREMENTAL_ROUTE_LEGACY_PARTIAL);
35713585
ASSERT_EQ(left, 1);
35723586
#endif

0 commit comments

Comments
 (0)