• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TEN-framework / ten-framework / 20358357829

19 Dec 2025 03:00AM UTC coverage: 57.587% (+0.2%) from 57.34%
20358357829

push

github

web-flow
fix: coveralls remove container for all test jobs (#1878)

* chore: calculate coverage in debug mode

* Revert "chore: calculate coverage in debug mode"

This reverts commit f68a031af.

* Reapply "chore: calculate coverage in debug mode"

This reverts commit bc27f2c1c.

* fix: remove container for test jobs

* fix: add C++ toolchain, go builder, sanitizer support, nodejs env

* fix: compiler version incompatible

* Revert "fix: compiler version incompatible"

This reverts commit 23f5c3f7d.

* fix: set PATH so that clang-21 is find earlier than older versions

* fix: uninstall older versions of clang

* Revert "fix: set PATH so that clang-21 is find earlier than older versions"

This reverts commit b66e56c08.

* fix: uninstall old clang first then install clang21

* fix: supplement test jobs deps according to tools Dockerfile

* fix: install libasan5 for all jobs and remove unecessary deps

* chore: refine codes and output clang version before every test

* fix: go back to clang 18 to detect __lsan_do_leak_check

* Revert "fix: go back to clang 18 to detect __lsan_do_leak_check"

This reverts commit d247818a8.

* fix: upgrade libasan5 to libasan8 to match clang 21

* fix: install libclang-rt-21-dev

* Revert "fix: install libclang-rt-21-dev"

This reverts commit 39b96e030.

* fix: ten_enable_go_app_leak_check

* chore: uninstall useless dep libasan8

* chore: refine codes and uninstall unecessary dep clang-tool-21

54480 of 94605 relevant lines covered (57.59%)

682622.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.59
/core/src/ten_runtime/addon_loader/addon_loader.c
1
//
2
// Copyright © 2025 Agora
3
// This file is part of TEN Framework, an open source project.
4
// Licensed under the Apache License, Version 2.0, with certain conditions.
5
// Refer to the "LICENSE" file in the root directory for more information.
6
//
7
#include "include_internal/ten_runtime/addon_loader/addon_loader.h"
8

9
#include "include_internal/ten_runtime/addon/addon_host.h"
10
#include "include_internal/ten_runtime/addon/addon_loader/addon_loader.h"
11
#include "include_internal/ten_runtime/addon/common/common.h"
12
#include "include_internal/ten_runtime/app/app.h"
13
#include "include_internal/ten_runtime/app/on_xxx.h"
14
#include "include_internal/ten_runtime/ten_env/ten_env.h"
15
#include "ten_runtime/app/app.h"
16
#include "ten_runtime/ten_env/ten_env.h"
17
#include "ten_utils/container/list.h"
18
#include "ten_utils/io/runloop.h"
19
#include "ten_utils/lib/signature.h"
20
#include "ten_utils/macro/memory.h"
21

22
bool ten_addon_loader_singleton_store_check_integrity(
23
    ten_addon_loader_singleton_store_t *store, bool check_thread) {
490✔
24
  TEN_ASSERT(store, "Invalid argument.");
490✔
25

26
  if (ten_signature_get(&store->signature) !=
490✔
27
      (ten_signature_t)TEN_ADDON_LOADER_SINGLETON_STORE_SIGNATURE) {
490✔
28
    return false;
×
29
  }
×
30

31
  if (check_thread) {
490✔
32
    return ten_sanitizer_thread_check_do_check(&store->thread_check);
50✔
33
  }
50✔
34

35
  return true;
440✔
36
}
490✔
37

38
void ten_addon_loader_singleton_store_init(
39
    ten_addon_loader_singleton_store_t *store) {
440✔
40
  TEN_ASSERT(store, "Can not init empty addon store.");
440✔
41
  ten_signature_set(&store->signature,
440✔
42
                    TEN_ADDON_LOADER_SINGLETON_STORE_SIGNATURE);
440✔
43
  ten_sanitizer_thread_check_init_with_current_thread(&store->thread_check);
440✔
44

45
  ten_list_init(&store->store);
440✔
46
}
440✔
47

48
void ten_addon_loader_singleton_store_deinit(
49
    ten_addon_loader_singleton_store_t *store) {
440✔
50
  TEN_ASSERT(store, "Invalid argument.");
440✔
51
  TEN_ASSERT(ten_addon_loader_singleton_store_check_integrity(store, false),
440✔
52
             "Invalid argument.");
440✔
53

54
  TEN_ASSERT(ten_list_is_empty(&store->store), "Should not happen.");
440✔
55

56
  ten_sanitizer_thread_check_deinit(&store->thread_check);
440✔
57
}
440✔
58

59
bool ten_addon_loader_check_integrity(ten_addon_loader_t *self,
60
                                      bool check_thread) {
60✔
61
  TEN_ASSERT(self, "Should not happen.");
60✔
62

63
  if (ten_signature_get(&self->signature) !=
60✔
64
      (ten_signature_t)TEN_ADDON_LOADER_SIGNATURE) {
60✔
65
    return false;
×
66
  }
×
67

68
  if (check_thread &&
60✔
69
      !ten_sanitizer_thread_check_do_check(&self->thread_check)) {
60✔
70
    return false;
×
71
  }
×
72

73
  return true;
60✔
74
}
60✔
75

76
ten_env_t *ten_addon_loader_get_ten_env(ten_addon_loader_t *self) {
5✔
77
  TEN_ASSERT(self, "Invalid argument.");
5✔
78
  TEN_ASSERT(ten_addon_loader_check_integrity(self, true), "Invalid argument.");
5✔
79

80
  return self->ten_env;
5✔
81
}
5✔
82

83
ten_addon_loader_t *ten_addon_loader_create(
84
    ten_addon_loader_on_init_func_t on_init,
85
    ten_addon_loader_on_deinit_func_t on_deinit,
86
    ten_addon_loader_on_load_addon_func_t on_load_addon) {
5✔
87
  ten_addon_loader_t *self =
5✔
88
      (ten_addon_loader_t *)TEN_MALLOC(sizeof(ten_addon_loader_t));
5✔
89
  TEN_ASSERT(self, "Failed to allocate memory.");
5✔
90

91
  ten_signature_set(&self->signature, TEN_ADDON_LOADER_SIGNATURE);
5✔
92
  ten_sanitizer_thread_check_init_with_current_thread(&self->thread_check);
5✔
93

94
  self->addon_host = NULL;
5✔
95

96
  self->on_init = on_init;
5✔
97
  self->on_deinit = on_deinit;
5✔
98
  self->on_load_addon = on_load_addon;
5✔
99

100
  self->on_init_done = NULL;
5✔
101
  self->on_init_done_data = NULL;
5✔
102

103
  self->ten_env = ten_env_create_for_addon_loader(self);
5✔
104

105
  return self;
5✔
106
}
5✔
107

108
void ten_addon_loader_destroy(ten_addon_loader_t *self) {
5✔
109
  TEN_ASSERT(self, "Invalid argument.");
5✔
110
  TEN_ASSERT(ten_addon_loader_check_integrity(self, true), "Invalid argument.");
5✔
111
  TEN_ASSERT(self->ten_env, "Should not happen.");
5✔
112

113
  ten_signature_set(&self->signature, 0);
5✔
114
  ten_sanitizer_thread_check_deinit(&self->thread_check);
5✔
115

116
  ten_env_destroy(self->ten_env);
5✔
117

118
  TEN_FREE(self);
5✔
119
}
5✔
120

121
static void ten_addon_loader_init(ten_addon_loader_t *self,
122
                                  ten_addon_loader_on_init_done_func_t cb,
123
                                  void *cb_data) {
5✔
124
  TEN_ASSERT(self, "Invalid argument.");
5✔
125
  TEN_ASSERT(ten_addon_loader_check_integrity(self, true), "Invalid argument.");
5✔
126

127
  self->on_init_done = cb;
5✔
128
  self->on_init_done_data = cb_data;
5✔
129

130
  if (self->on_init) {
5✔
131
    self->on_init(self, self->ten_env);
5✔
132
  } else {
5✔
133
    ten_env_on_init_done(self->ten_env, NULL);
×
134
  }
×
135
}
5✔
136

137
static void ten_addon_loader_deinit(ten_addon_loader_t *self,
138
                                    ten_addon_loader_on_deinit_done_func_t cb,
139
                                    void *cb_data) {
5✔
140
  TEN_ASSERT(self, "Invalid argument.");
5✔
141
  TEN_ASSERT(ten_addon_loader_check_integrity(self, true), "Invalid argument.");
5✔
142

143
  self->on_deinit_done = cb;
5✔
144
  self->on_deinit_done_data = cb_data;
5✔
145

146
  if (self->on_deinit) {
5✔
147
    self->on_deinit(self, self->ten_env);
5✔
148
  } else {
5✔
149
    ten_env_on_deinit_done(self->ten_env, NULL);
×
150
  }
×
151
}
5✔
152

153
void ten_addon_loader_load_addon(ten_addon_loader_t *self,
154
                                 TEN_ADDON_TYPE addon_type,
155
                                 const char *addon_name,
156
                                 ten_addon_loader_on_load_addon_done_func_t cb,
157
                                 void *cb_data) {
×
158
  TEN_ASSERT(self, "Invalid argument.");
×
159
  TEN_ASSERT(ten_addon_loader_check_integrity(self, true), "Invalid argument.");
×
160

161
  ten_addon_loader_load_addon_ctx_t *ctx =
×
162
      TEN_MALLOC(sizeof(ten_addon_loader_load_addon_ctx_t));
×
163
  TEN_ASSERT(ctx, "Failed to allocate memory.");
×
164

165
  ctx->cb = cb;
×
166
  ctx->cb_data = cb_data;
×
167

168
  TEN_ASSERT(self->on_load_addon, "Should not happen.");
×
169
  self->on_load_addon(self, self->ten_env, addon_type, addon_name, ctx);
×
170
}
×
171

172
bool ten_addon_loader_on_load_addon_done(ten_env_t *ten_env, void *context) {
×
173
  TEN_ASSERT(ten_env, "Invalid argument.");
×
174
  TEN_ASSERT(ten_env_check_integrity(ten_env, true), "Invalid argument.");
×
175
  TEN_ASSERT(ten_env_get_attach_to(ten_env) == TEN_ENV_ATTACH_TO_ADDON_LOADER,
×
176
             "Should not happen.");
×
177

178
  ten_addon_loader_load_addon_ctx_t *ctx =
×
179
      (ten_addon_loader_load_addon_ctx_t *)context;
×
180
  TEN_ASSERT(ctx, "Invalid argument.");
×
181

182
  if (ctx->cb) {
×
183
    ctx->cb(ten_env, ctx->cb_data);
×
184
  }
×
185

186
  TEN_FREE(ctx);
×
187

188
  return true;
×
189
}
×
190

191
static void ten_app_thread_on_addon_loader_init_done(void *app_,
192
                                                     void *cb_data) {
5✔
193
  ten_app_t *app = (ten_app_t *)app_;
5✔
194
  TEN_ASSERT(app, "Invalid argument.");
5✔
195
  TEN_ASSERT(ten_app_check_integrity(app, true), "Invalid argument.");
5✔
196

197
  ten_addon_loader_singleton_store_t *store =
5✔
198
      &app->addon_loader_singleton_store;
5✔
199
  TEN_ASSERT(store, "Should not happen.");
5✔
200
  TEN_ASSERT(ten_addon_loader_singleton_store_check_integrity(store, true),
5✔
201
             "Should not happen.");
5✔
202

203
  ten_app_on_addon_loader_init_done_ctx_t *ctx =
5✔
204
      (ten_app_on_addon_loader_init_done_ctx_t *)cb_data;
5✔
205
  TEN_ASSERT(ctx, "Invalid argument.");
5✔
206

207
  ten_addon_loader_on_all_singleton_instances_created_ctx_t
5✔
208
      *on_all_created_ctx = ctx->cb_data;
5✔
209
  TEN_ASSERT(on_all_created_ctx, "Invalid argument.");
5✔
210

211
  size_t desired_count = on_all_created_ctx->desired_count;
5✔
212

213
  ten_list_push_ptr_back(&store->store, ctx->addon_loader, NULL);
5✔
214

215
  TEN_FREE(ctx);
5✔
216

217
  if (ten_list_size(&store->store) == desired_count) {
5✔
218
    // Call the callback to notify all addon_loader instances have been created.
219
    on_all_created_ctx->cb(on_all_created_ctx->ten_env,
5✔
220
                           on_all_created_ctx->cb_data);
5✔
221

222
    TEN_FREE(on_all_created_ctx);
5✔
223
  }
5✔
224
}
5✔
225

226
static void ten_app_thread_on_addon_loader_deinit_done(void *app_,
227
                                                       void *cb_data) {
5✔
228
  ten_app_t *app = (ten_app_t *)app_;
5✔
229
  TEN_ASSERT(app, "Invalid argument.");
5✔
230
  TEN_ASSERT(ten_app_check_integrity(app, true), "Invalid argument.");
5✔
231

232
  ten_addon_loader_singleton_store_t *store =
5✔
233
      &app->addon_loader_singleton_store;
5✔
234
  TEN_ASSERT(store, "Should not happen.");
5✔
235
  TEN_ASSERT(ten_addon_loader_singleton_store_check_integrity(store, true),
5✔
236
             "Should not happen.");
5✔
237

238
  ten_app_on_addon_loader_deinit_done_ctx_t *ctx =
5✔
239
      (ten_app_on_addon_loader_deinit_done_ctx_t *)cb_data;
5✔
240
  TEN_ASSERT(ctx, "Invalid argument.");
5✔
241

242
  ten_addon_loader_on_all_singleton_instances_destroyed_ctx_t
5✔
243
      *on_all_destroyed_ctx = ctx->cb_data;
5✔
244
  TEN_ASSERT(on_all_destroyed_ctx, "Invalid argument.");
5✔
245

246
  ten_addon_loader_t *addon_loader = ctx->addon_loader;
5✔
247
  TEN_ASSERT(addon_loader, "Invalid argument.");
5✔
248
  TEN_ASSERT(ten_addon_loader_check_integrity(addon_loader, true),
5✔
249
             "Invalid argument.");
5✔
250

251
  ten_addon_host_t *addon_host = addon_loader->addon_host;
5✔
252
  TEN_ASSERT(addon_host, "Should not happen.");
5✔
253

254
  addon_host->addon->on_destroy_instance(addon_host->addon, addon_host->ten_env,
5✔
255
                                         addon_loader, NULL);
5✔
256

257
  ten_list_remove_ptr(&store->store, addon_loader);
5✔
258

259
  if (ten_list_size(&store->store) == 0) {
5✔
260
    if (on_all_destroyed_ctx->cb) {
5✔
261
      on_all_destroyed_ctx->cb(on_all_destroyed_ctx->ten_env,
5✔
262
                               on_all_destroyed_ctx->cb_data);
5✔
263
    }
5✔
264

265
    TEN_FREE(on_all_destroyed_ctx);
5✔
266
  }
5✔
267

268
  TEN_FREE(ctx);
5✔
269
}
5✔
270

271
static void ten_addon_loader_init_done(ten_env_t *ten_env, void *cb_data) {
5✔
272
  TEN_ASSERT(ten_env, "Invalid argument.");
5✔
273
  TEN_ASSERT(ten_env_check_integrity(ten_env, true), "Invalid argument.");
5✔
274
  TEN_ASSERT(cb_data, "Invalid argument.");
5✔
275

276
  ten_addon_loader_t *addon_loader = ten_env_get_attached_addon_loader(ten_env);
5✔
277
  TEN_ASSERT(addon_loader, "Should not happen.");
5✔
278
  TEN_ASSERT(ten_addon_loader_check_integrity(addon_loader, true),
5✔
279
             "Should not happen.");
5✔
280

281
  ten_addon_loader_on_all_singleton_instances_created_ctx_t *ctx =
5✔
282
      (ten_addon_loader_on_all_singleton_instances_created_ctx_t *)cb_data;
5✔
283
  TEN_ASSERT(ctx, "Invalid argument.");
5✔
284

285
  ten_env_t *caller_ten_env = ctx->ten_env;
5✔
286
  TEN_ASSERT(caller_ten_env, "Invalid argument.");
5✔
287
  // TEN_NOLINTNEXTLINE(thread-check)
288
  // thread-check: This function is intended to be called in any threads.
289
  TEN_ASSERT(ten_env_check_integrity(caller_ten_env, false),
5✔
290
             "Invalid argument.");
5✔
291

292
  TEN_ASSERT(caller_ten_env->attach_to == TEN_ENV_ATTACH_TO_APP,
5✔
293
             "Should not happen.");
5✔
294

295
  ten_app_t *app = ten_env_get_attached_app(caller_ten_env);
5✔
296
  TEN_ASSERT(app, "Invalid argument.");
5✔
297
  // TEN_NOLINTNEXTLINE(thread-check)
298
  // thread-check: This function is intended to be called in any threads.
299
  TEN_ASSERT(ten_app_check_integrity(app, false), "Invalid argument.");
5✔
300

301
  ten_app_on_addon_loader_init_done_ctx_t *on_addon_loader_init_done_ctx =
5✔
302
      TEN_MALLOC(sizeof(ten_app_on_addon_loader_init_done_ctx_t));
5✔
303
  TEN_ASSERT(on_addon_loader_init_done_ctx, "Should not happen.");
5✔
304

305
  on_addon_loader_init_done_ctx->addon_loader = addon_loader;
5✔
306
  on_addon_loader_init_done_ctx->cb_data = ctx;
5✔
307

308
  int rc = ten_runloop_post_task_tail(ten_app_get_attached_runloop(app),
5✔
309
                                      ten_app_thread_on_addon_loader_init_done,
5✔
310
                                      app, on_addon_loader_init_done_ctx);
5✔
311
  if (rc) {
5✔
312
    TEN_LOGE("Failed to post task to app runloop");
×
313
    TEN_ASSERT(0, "Should not happen.");
×
314
  }
×
315
}
5✔
316

317
static void create_addon_loader_done(ten_env_t *ten_env,
318
                                     ten_addon_loader_t *addon_loader,
319
                                     void *cb_data) {
5✔
320
  TEN_ASSERT(ten_env, "Invalid argument.");
5✔
321
  TEN_ASSERT(ten_env_check_integrity(ten_env, true), "Invalid argument.");
5✔
322
  TEN_ASSERT(
5✔
323
      addon_loader && ten_addon_loader_check_integrity(addon_loader, true),
5✔
324
      "Invalid argument.");
5✔
325
  TEN_ASSERT(ten_env_get_attach_to(ten_env) == TEN_ENV_ATTACH_TO_APP,
5✔
326
             "Invalid argument.");
5✔
327

328
  ten_app_t *app = ten_env_get_attached_target(ten_env);
5✔
329
  TEN_ASSERT(app, "Invalid argument.");
5✔
330
  TEN_ASSERT(ten_app_check_integrity(app, true), "Invalid argument.");
5✔
331

332
  // Call `on_init` of the addon_loader to initialize the addon_loader.
333
  ten_addon_loader_init(addon_loader, ten_addon_loader_init_done, cb_data);
5✔
334
}
5✔
335

336
static ten_addon_loader_on_all_singleton_instances_created_ctx_t *
337
ten_addon_loader_on_all_singleton_instances_created_ctx_create(
338
    ten_env_t *ten_env, size_t desired_count,
339
    ten_addon_loader_on_all_singleton_instances_created_cb_t cb,
340
    void *cb_data) {
5✔
341
  ten_addon_loader_on_all_singleton_instances_created_ctx_t *ctx = TEN_MALLOC(
5✔
342
      sizeof(ten_addon_loader_on_all_singleton_instances_created_ctx_t));
5✔
343
  TEN_ASSERT(ctx, "Should not happen.");
5✔
344

345
  ctx->ten_env = ten_env;
5✔
346
  ctx->desired_count = desired_count;
5✔
347
  ctx->cb = cb;
5✔
348
  ctx->cb_data = cb_data;
5✔
349

350
  return ctx;
5✔
351
}
5✔
352

353
static ten_addon_loader_on_all_singleton_instances_destroyed_ctx_t *
354
ten_addon_loader_on_all_singleton_instances_destroyed_ctx_create(
355
    ten_env_t *ten_env,
356
    ten_addon_loader_on_all_singleton_instances_destroyed_cb_t cb,
357
    void *cb_data) {
5✔
358
  ten_addon_loader_on_all_singleton_instances_destroyed_ctx_t *ctx = TEN_MALLOC(
5✔
359
      sizeof(ten_addon_loader_on_all_singleton_instances_destroyed_ctx_t));
5✔
360
  TEN_ASSERT(ctx, "Failed to allocate memory.");
5✔
361

362
  ctx->ten_env = ten_env;
5✔
363
  ctx->cb = cb;
5✔
364
  ctx->cb_data = cb_data;
5✔
365

366
  return ctx;
5✔
367
}
5✔
368

369
void ten_addon_loader_addons_create_singleton_instance(
370
    ten_env_t *ten_env,
371
    ten_addon_loader_on_all_singleton_instances_created_cb_t cb,
372
    void *cb_data) {
17✔
373
  bool need_to_wait_all_addon_loaders_created = true;
17✔
374

375
  ten_app_t *app = ten_env_get_attached_app(ten_env);
17✔
376
  TEN_ASSERT(app, "Should not happen.");
17✔
377
  TEN_ASSERT(ten_app_check_integrity(app, true), "Should not happen.");
17✔
378

379
  ten_addon_store_t *addon_loader_store = &app->addon_loader_store;
17✔
380
  TEN_ASSERT(addon_loader_store, "Should not happen.");
17✔
381
  TEN_ASSERT(ten_addon_store_check_integrity(addon_loader_store, true),
17✔
382
             "Should not happen.");
17✔
383

384
  ten_addon_loader_singleton_store_t *addon_loader_singleton_store =
17✔
385
      &app->addon_loader_singleton_store;
17✔
386
  TEN_ASSERT(addon_loader_singleton_store, "Should not happen.");
17✔
387
  TEN_ASSERT(ten_addon_loader_singleton_store_check_integrity(
17✔
388
                 addon_loader_singleton_store, true),
17✔
389
             "Should not happen.");
17✔
390

391
  size_t desired_count = ten_list_size(&addon_loader_store->store);
17✔
392
  if (!desired_count ||
17✔
393
      ten_list_size(&addon_loader_singleton_store->store) == desired_count) {
17✔
394
    need_to_wait_all_addon_loaders_created = false;
12✔
395
    goto done;
12✔
396
  }
12✔
397

398
  ten_addon_loader_on_all_singleton_instances_created_ctx_t *ctx =
5✔
399
      ten_addon_loader_on_all_singleton_instances_created_ctx_create(
5✔
400
          ten_env, desired_count, cb, cb_data);
5✔
401
  TEN_ASSERT(ctx, "Should not happen.");
5✔
402

403
  ten_error_t err;
5✔
404
  TEN_ERROR_INIT(err);
5✔
405

406
  ten_list_foreach (&addon_loader_store->store, iter) {
5✔
407
    ten_addon_host_t *loader_addon_host = ten_ptr_listnode_get(iter.node);
5✔
408
    TEN_ASSERT(loader_addon_host, "Should not happen.");
5✔
409

410
    bool res = ten_addon_create_addon_loader(
5✔
411
        ten_env, ten_string_get_raw_str(&loader_addon_host->name),
5✔
412
        ten_string_get_raw_str(&loader_addon_host->name),
5✔
413
        (ten_env_addon_create_instance_done_cb_t)create_addon_loader_done, ctx,
5✔
414
        &err);
5✔
415

416
    if (!res) {
5✔
417
      TEN_LOGE("Failed to create addon_loader instance %s, %s",
×
418
               ten_string_get_raw_str(&loader_addon_host->name),
×
419
               ten_error_message(&err));
×
420
#if defined(_DEBUG)
×
421
      TEN_ASSERT(0, "Should not happen.");
×
422
#endif
×
423
    }
×
424
  }
5✔
425

426
  ten_error_deinit(&err);
5✔
427

428
done:
17✔
429
  if (!need_to_wait_all_addon_loaders_created && cb) {
17✔
430
    cb(ten_env, cb_data);
12✔
431
  }
12✔
432
}
17✔
433

434
static void ten_addon_loader_deinit_done(ten_env_t *ten_env, void *cb_data) {
5✔
435
  TEN_ASSERT(ten_env, "Invalid argument.");
5✔
436
  TEN_ASSERT(ten_env_check_integrity(ten_env, true), "Invalid argument.");
5✔
437
  TEN_ASSERT(cb_data, "Invalid argument.");
5✔
438

439
  ten_addon_loader_t *addon_loader = ten_env_get_attached_addon_loader(ten_env);
5✔
440
  TEN_ASSERT(addon_loader, "Should not happen.");
5✔
441
  TEN_ASSERT(ten_addon_loader_check_integrity(addon_loader, true),
5✔
442
             "Should not happen.");
5✔
443

444
  ten_addon_loader_on_all_singleton_instances_destroyed_ctx_t *ctx =
5✔
445
      (ten_addon_loader_on_all_singleton_instances_destroyed_ctx_t *)cb_data;
5✔
446
  TEN_ASSERT(ctx, "Invalid argument.");
5✔
447

448
  ten_env_t *caller_ten_env = ctx->ten_env;
5✔
449
  TEN_ASSERT(caller_ten_env, "Invalid argument.");
5✔
450
  // TEN_NOLINTNEXTLINE(thread-check)
451
  // thread-check: This function is intended to be called in any threads.
452
  TEN_ASSERT(ten_env_check_integrity(caller_ten_env, false),
5✔
453
             "Invalid argument.");
5✔
454

455
  TEN_ASSERT(caller_ten_env->attach_to == TEN_ENV_ATTACH_TO_APP,
5✔
456
             "Should not happen.");
5✔
457

458
  ten_app_t *app = ten_env_get_attached_app(caller_ten_env);
5✔
459
  TEN_ASSERT(app, "Invalid argument.");
5✔
460
  // TEN_NOLINTNEXTLINE(thread-check)
461
  // thread-check: This function is intended to be called in any threads.
462
  TEN_ASSERT(ten_app_check_integrity(app, false), "Invalid argument.");
5✔
463

464
  ten_app_on_addon_loader_deinit_done_ctx_t *on_addon_loader_deinit_done_ctx =
5✔
465
      TEN_MALLOC(sizeof(ten_app_on_addon_loader_deinit_done_ctx_t));
5✔
466
  TEN_ASSERT(on_addon_loader_deinit_done_ctx, "Should not happen.");
5✔
467

468
  on_addon_loader_deinit_done_ctx->addon_loader = addon_loader;
5✔
469
  on_addon_loader_deinit_done_ctx->cb_data = ctx;
5✔
470

471
  int rc =
5✔
472
      ten_runloop_post_task_tail(ten_app_get_attached_runloop(app),
5✔
473
                                 ten_app_thread_on_addon_loader_deinit_done,
5✔
474
                                 app, on_addon_loader_deinit_done_ctx);
5✔
475
  if (rc) {
5✔
476
    TEN_LOGE("Failed to post task to app runloop");
×
477
    TEN_ASSERT(0, "Should not happen.");
×
478
  }
×
479
}
5✔
480

481
void ten_addon_loader_destroy_all_singleton_instances(
482
    ten_env_t *ten_env,
483
    ten_addon_loader_on_all_singleton_instances_destroyed_cb_t cb,
484
    void *cb_data) {
17✔
485
  TEN_ASSERT(ten_env, "Invalid argument.");
17✔
486
  TEN_ASSERT(ten_env_check_integrity(ten_env, true), "Invalid argument.");
17✔
487

488
  TEN_ASSERT(ten_env_get_attach_to(ten_env) == TEN_ENV_ATTACH_TO_APP,
17✔
489
             "Should not happen.");
17✔
490

491
  ten_app_t *app = ten_env_get_attached_app(ten_env);
17✔
492
  TEN_ASSERT(app, "Should not happen.");
17✔
493
  TEN_ASSERT(ten_app_check_integrity(app, true), "Should not happen.");
17✔
494

495
  ten_addon_loader_singleton_store_t *addon_loader_singleton_store =
17✔
496
      &app->addon_loader_singleton_store;
17✔
497
  TEN_ASSERT(addon_loader_singleton_store, "Should not happen.");
17✔
498
  TEN_ASSERT(ten_addon_loader_singleton_store_check_integrity(
17✔
499
                 addon_loader_singleton_store, true),
17✔
500
             "Should not happen.");
17✔
501

502
  bool need_to_wait_all_addon_loaders_destroyed = true;
17✔
503

504
  if (ten_list_size(&addon_loader_singleton_store->store) == 0) {
17✔
505
    need_to_wait_all_addon_loaders_destroyed = false;
12✔
506
    goto done;
12✔
507
  }
12✔
508

509
  ten_addon_loader_on_all_singleton_instances_destroyed_ctx_t *ctx =
5✔
510
      ten_addon_loader_on_all_singleton_instances_destroyed_ctx_create(
5✔
511
          ten_env, cb, cb_data);
5✔
512
  TEN_ASSERT(ctx, "Should not happen.");
5✔
513

514
  ten_list_foreach (&addon_loader_singleton_store->store, iter) {
10✔
515
    ten_addon_loader_t *addon_loader = ten_ptr_listnode_get(iter.node);
5✔
516
    TEN_ASSERT(addon_loader, "Should not happen.");
5✔
517
    TEN_ASSERT(ten_addon_loader_check_integrity(addon_loader, true),
5✔
518
               "Should not happen.");
5✔
519

520
    ten_addon_host_t *addon_host = addon_loader->addon_host;
5✔
521
    TEN_ASSERT(addon_host, "Should not happen.");
5✔
522
    TEN_ASSERT(ten_addon_host_check_integrity(addon_host, true),
5✔
523
               "Should not happen.");
5✔
524

525
    ten_addon_loader_deinit(addon_loader, ten_addon_loader_deinit_done, ctx);
5✔
526
  }
5✔
527

528
done:
17✔
529
  if (!need_to_wait_all_addon_loaders_destroyed && cb) {
17✔
530
    cb(ten_env, cb_data);
12✔
531
  }
12✔
532
}
17✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc