@fastybird/smart-panel-backend 1.1.0-alpha.17 → 1.1.0-alpha.18

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.
@@ -23,7 +23,11 @@ QUIESCENCE_TIMEOUT_SECONDS="${QUIESCENCE_TIMEOUT_SECONDS:-30}"
23
23
  START_TIMEOUT_SECONDS="${START_TIMEOUT_SECONDS:-60}"
24
24
  HEALTH_URL="${HEALTH_URL:-}"
25
25
  CAPTURED_SERVICE_CGROUP_PROCS=""
26
+ CAPTURED_SERVICE_CGROUP_DIR=""
27
+ CAPTURED_SERVICE_CGROUP_EVENTS=""
26
28
  CAPTURED_SERVICE_MEMBER_IDENTITIES=""
29
+ CGROUP_MEMBERS=""
30
+ CGROUP_POPULATED=""
27
31
 
28
32
  json_escape() {
29
33
  printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g; s/[[:cntrl:]]//g'
@@ -203,8 +207,86 @@ process_identity() {
203
207
  printf '%s|%s\n' "$pid" "$command"
204
208
  }
205
209
 
210
+ read_cgroup_members() {
211
+ local cgroup_procs="$1"
212
+ local contents members
213
+
214
+ CGROUP_MEMBERS=""
215
+ if ! contents="$(cat "$cgroup_procs" 2>/dev/null)"; then
216
+ return 2
217
+ fi
218
+
219
+ if ! members="$(printf '%s\n' "$contents" | awk '
220
+ length($0) > 0 {
221
+ if ($0 !~ /^[0-9]+$/) {
222
+ exit 2
223
+ }
224
+ print
225
+ }
226
+ ')"; then
227
+ return 2
228
+ fi
229
+
230
+ CGROUP_MEMBERS="$members"
231
+ }
232
+
233
+ read_cgroup_population() {
234
+ local cgroup_events="$1"
235
+ local contents populated
236
+
237
+ CGROUP_POPULATED=""
238
+ if ! contents="$(cat "$cgroup_events" 2>/dev/null)"; then
239
+ return 2
240
+ fi
241
+
242
+ if ! populated="$(printf '%s\n' "$contents" | awk '
243
+ $1 == "populated" {
244
+ count++
245
+ if (NF != 2 || $2 !~ /^[01]$/) {
246
+ invalid=1
247
+ } else {
248
+ value=$2
249
+ }
250
+ }
251
+ END {
252
+ if (count != 1 || invalid) {
253
+ exit 2
254
+ }
255
+ print value
256
+ }
257
+ ')"; then
258
+ return 2
259
+ fi
260
+
261
+ CGROUP_POPULATED="$populated"
262
+ }
263
+
264
+ probe_cgroup_directory() {
265
+ local cgroup_dir="$1"
266
+ local gnu_stat bsd_stat
267
+
268
+ if gnu_stat="$(LC_ALL=C stat -c '%F' "$cgroup_dir" 2>&1)"; then
269
+ case "$gnu_stat" in
270
+ directory) return 0 ;;
271
+ *) return 2 ;;
272
+ esac
273
+ fi
274
+
275
+ if bsd_stat="$(LC_ALL=C stat -f '%HT' "$cgroup_dir" 2>&1)"; then
276
+ case "$bsd_stat" in
277
+ Directory|directory) return 0 ;;
278
+ *) return 2 ;;
279
+ esac
280
+ fi
281
+
282
+ case "$gnu_stat\n$bsd_stat" in
283
+ *"No such file or directory"*|*"no such file or directory"*) return 1 ;;
284
+ *) return 2 ;;
285
+ esac
286
+ }
287
+
206
288
  capture_service_identity() {
207
- local active_state main_pid control_pid control_group cgroup_procs members pid identity
289
+ local active_state main_pid control_pid control_group cgroup_procs cgroup_dir cgroup_events members pid identity member_status
208
290
 
209
291
  active_state="$(service_property ActiveState 2>/dev/null)" || return 2
210
292
  main_pid="$(service_property MainPID 2>/dev/null)" || return 2
@@ -221,8 +303,18 @@ capture_service_identity() {
221
303
  [ -n "$control_group" ] || return 2
222
304
 
223
305
  cgroup_procs="${SERVICE_CGROUP_PROCS_FILE:-/sys/fs/cgroup${control_group}/cgroup.procs}"
306
+ cgroup_dir="${SERVICE_CGROUP_DIR:-${cgroup_procs%/cgroup.procs}}"
307
+ cgroup_events="${SERVICE_CGROUP_EVENTS_FILE:-${cgroup_dir}/cgroup.events}"
308
+ if probe_cgroup_directory "$cgroup_dir"; then :; else return 2; fi
224
309
  [ -r "$cgroup_procs" ] || return 2
225
- members="$(grep -E '^[0-9]+$' "$cgroup_procs" 2>/dev/null)" || true
310
+ [ -r "$cgroup_events" ] || return 2
311
+ if read_cgroup_members "$cgroup_procs"; then
312
+ member_status=0
313
+ else
314
+ member_status=$?
315
+ fi
316
+ [ "$member_status" -eq 0 ] || return "$member_status"
317
+ members="$CGROUP_MEMBERS"
226
318
  [ -n "$members" ] || return 1
227
319
 
228
320
  CAPTURED_SERVICE_MEMBER_IDENTITIES=""
@@ -236,10 +328,12 @@ EOF
236
328
 
237
329
  printf '%s\n' "$members" | grep -qx "$main_pid" || return 1
238
330
  CAPTURED_SERVICE_CGROUP_PROCS="$cgroup_procs"
331
+ CAPTURED_SERVICE_CGROUP_DIR="$cgroup_dir"
332
+ CAPTURED_SERVICE_CGROUP_EVENTS="$cgroup_events"
239
333
  }
240
334
 
241
335
  service_quiesced() {
242
- local active_state main_pid control_pid cgroup_contents current_members pid captured_identity current_identity identity_status
336
+ local active_state main_pid control_pid cgroup_dir_status member_status population_status probe_status pid captured_identity current_identity identity_status
243
337
 
244
338
  [ -n "$CAPTURED_SERVICE_CGROUP_PROCS" ] || return 2
245
339
  active_state="$(service_property ActiveState 2>/dev/null)" || return 2
@@ -275,15 +369,48 @@ $(printf '%b' "$CAPTURED_SERVICE_MEMBER_IDENTITIES")
275
369
  EOF
276
370
 
277
371
  # The original cgroup may be empty or removed after the service reaches inactive/failed with
278
- # zero MainPID/ControlPID. If it still exists, it must be readable and contain no members.
279
- if [ -e "$CAPTURED_SERVICE_CGROUP_PROCS" ]; then
280
- [ -r "$CAPTURED_SERVICE_CGROUP_PROCS" ] || return 2
281
- if ! cgroup_contents="$(cat "$CAPTURED_SERVICE_CGROUP_PROCS" 2>/dev/null)"; then
282
- [ ! -e "$CAPTURED_SERVICE_CGROUP_PROCS" ] || return 2
283
- cgroup_contents=""
372
+ # zero MainPID/ControlPID. A missing membership file while its directory remains is an
373
+ # unavailable probe, not proof that the subtree is empty.
374
+ if probe_cgroup_directory "$CAPTURED_SERVICE_CGROUP_DIR"; then
375
+ if read_cgroup_members "$CAPTURED_SERVICE_CGROUP_PROCS"; then
376
+ member_status=0
377
+ else
378
+ member_status=$?
379
+ fi
380
+ if [ "$member_status" -eq 2 ]; then
381
+ if probe_cgroup_directory "$CAPTURED_SERVICE_CGROUP_DIR"; then
382
+ return 2
383
+ else
384
+ probe_status=$?
385
+ fi
386
+ [ "$probe_status" -eq 1 ] || return 2
387
+ return 0
388
+ fi
389
+ [ "$member_status" -eq 0 ] || return "$member_status"
390
+ [ -z "$CGROUP_MEMBERS" ] || return 1
391
+
392
+ if read_cgroup_population "$CAPTURED_SERVICE_CGROUP_EVENTS"; then
393
+ population_status=0
394
+ else
395
+ population_status=$?
396
+ fi
397
+ if [ "$population_status" -eq 2 ]; then
398
+ if probe_cgroup_directory "$CAPTURED_SERVICE_CGROUP_DIR"; then
399
+ return 2
400
+ else
401
+ probe_status=$?
402
+ fi
403
+ [ "$probe_status" -eq 1 ] || return 2
404
+ return 0
284
405
  fi
285
- current_members="$(printf '%s\n' "$cgroup_contents" | grep -E '^[0-9]+$')" || true
286
- [ -z "$current_members" ] || return 1
406
+ [ "$population_status" -eq 0 ] || return "$population_status"
407
+ [ "$CGROUP_POPULATED" = "0" ] || return 1
408
+ else
409
+ cgroup_dir_status=$?
410
+ case "$cgroup_dir_status" in
411
+ 1) ;;
412
+ *) return 2 ;;
413
+ esac
287
414
  fi
288
415
 
289
416
  return 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastybird/smart-panel-backend",
3
- "version": "1.1.0-alpha.17",
3
+ "version": "1.1.0-alpha.18",
4
4
  "description": "Powerful backend for administrating and integrating the FastyBird IoT Smart Panel",
5
5
  "keywords": [
6
6
  "fastybird",
@@ -112,7 +112,7 @@
112
112
  "ws": "^8.19.0",
113
113
  "yaml": "^2.8.2",
114
114
  "zod": "4.4.3",
115
- "@fastybird/smart-panel-extension-sdk": "1.1.0-alpha.17"
115
+ "@fastybird/smart-panel-extension-sdk": "1.1.0-alpha.18"
116
116
  },
117
117
  "devDependencies": {
118
118
  "@eslint/eslintrc": "^3.3.5",