Skip to content

POST /config/objects corrupts Storable cache file under concurrent requests #1497

Description

@ccztux

Description

When multiple POST /config/objects requests are sent concurrently to the Thruk REST API, the internal Perl Storable cache file (Thruk::Utils::Conf, line 754) becomes corrupted. This causes a random subset of objects to be silently dropped — no HTTP error is returned to the caller, yet the objects are never persisted.

Steps to Reproduce

#!/bin/bash
# Reproduces the concurrent /config/objects race condition.
# Sends 300 parallel POST requests, each creating a dummy host object.
# Requires: curl, bash 4+

THRUK_URL="https://localhost/thruk/r"
AUTH_TOKEN="your-api-key"


for i in $(seq 1 300); do
  curl -sk \
    -H "X-Thruk-Auth-Key: ${AUTH_TOKEN}" \
    -H "Content-Type: application/json" \
    -X POST "${THRUK_URL}/config/objects" \
    -d "{
      \":TYPE\": \"host\",
      \":FILE\": \"nagios_host.cfg\",
      \"host_name\": \"race-test-host-${i}\",
      \"alias\": \"Race Test Host ${i}\",
      \"address\": \"192.168.99.${i}\",
      \"register\": 1
    }" \
    --output /tmp/race_result_${i}.json &
done

wait

echo "Results:"
for i in $(seq 1 300); do
  echo -n "  host-${i}: "
  cat /tmp/race_result_${i}.json | python3 -c \
    "import sys,json; d=json.load(sys.stdin); print(d.get('failed','?'), d.get('message', d.get(':ID','ok')))" \
    2>/dev/null || cat /tmp/race_result_${i}.json
done

Observed Behavior

The following errors appear in /var/log/thruk/thruk.log

[ERROR] Magic number checking on storable file failed at .../Thruk/Utils/Conf.pm line 754.
[ERROR] Corrupted storable file (binary v2.11) at .../Thruk/Utils/Conf.pm line 754.
[ERROR] Class name #4 should have been seen already at .../Thruk/Utils/Conf.pm line 754.
[WARN]  backend 328c5 returned error: configuration is being parsed right now, try again in a few moments

Only a fraction of the submitted objects are actually created. The remaining requests return HTTP 200 with "created 1 objects successfully." — yet the objects are missing after /config/save.

Expected Behavior

Either:

Concurrent POST /config/objects requests are serialized internally (e.g. via file lock on the Storable cache), so all objects are created correctly, or
The endpoint returns HTTP 409 Conflict or 503 Service Unavailable when a concurrent write is already in progress, so callers can detect the condition and retry

Environment

Thruk version: 3.26
OS: RHEL 8
Naemon version: 1.4.1

Impact

Automation tools that batch-create monitoring objects (e.g. 20 hosts × 54 services/commands = 1080 objects) cannot use any parallelism. With ~0.6 s per sequential request, a single batch job takes ~11 minutes. A server-side batch insert endpoint or internal write serialization would significantly improve usability.

Workaround

Serialize all POST /config/objects calls to a single thread. Resolves the corruption but eliminates parallelism entirely.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions