-
Notifications
You must be signed in to change notification settings - Fork 2k
Open
Description
Problem Description
When using yaml-cpp in multithreaded scenarios to check undefined nodes via IsDefined()
and reset()
methods, the program occasionally crashes with segmentation faults or double-free errors. The crash occurs even with read-only operations and no explicit node modifications.
Minimal Reproduction
#include <yaml-cpp/yaml.h>
#include <thread>
#include <vector>
YAML::Node rootNode(YAML::NodeType::Map);
YAML::Node foo() {
YAML::Node node;
node.reset(rootNode);
if (!node.IsDefined()) {
return node;
}
node.reset(node["a"]); // undefined
if (!node.IsDefined()) {
return node;
}
return node;
}
int main() {
std::vector<std::thread> threads;
for (int i = 0; i < 16; ++i) {
threads.emplace_back(foo);
}
for (auto& t : threads) {
t.join();
}
}
Reproduction Script
#!/bin/bash
PROGRAM="./bazel-bin/src/main"
if [ ! -x "$PROGRAM" ]; then
echo "Error: Program '$PROGRAM' not found or not executable."
exit 1
fi
echo "Running $PROGRAM until crash occurs..."
count=0
while true; do
count=$((count+1))
$PROGRAM
exit_code=$?
if [ $exit_code -ne 0 ]; then
echo "Program finished with exit code $exit_code"
break
fi
done
echo "Program crashed after $count runs"
Discovery Context
The crash manifests in real-world code resembling this pattern:
YAML::Node GetNode(std::string_view keyPath) {
std::vector<std::string> keys = split(keyPath, ".");
YAML::Node node;
node.reset(rootNode);
for (const auto& key : keys) {
if (!node) break;
node.reset(node[key]);
}
return node;
}
This pattern is used extensively for configuration parsing. Despite being read-only and not modifying any nodes, concurrent access causes crashes.
Requests
- Is this a known thread-safety limitation of yaml-cpp's reference-counted nodes?
- What is the recommended pattern for concurrent read-only access to YAML configurations?
Metadata
Metadata
Assignees
Labels
No labels