librdkafka
librdkafka copied to clipboard
Covscan defect finding: LOCK_EVASION
Description
I've scheduled a covscan analysis for librdkafka and I would like to ask if the reported defect is valid. The issue was found on an older version but it is reproducible on the current version as well.
How to reproduce
First - rd_kafka_toppar_consumer_lag_req():
1. rdkafka_partition.c: thread1_checks_field: Thread1 uses the value read from field "rktp_wait_consumer_lag_resp" in the condition "rktp->rktp_wait_consumer_lag_resp". It sees that the condition is false. Control is switched to Thread2.
2. rdkafka_partition.c: thread2_checks_field: Thread2 uses the value read from field "rktp_wait_consumer_lag_resp" in the condition "rktp->rktp_wait_consumer_lag_resp". It sees that the condition is false.
3. rdkafka_partition.c: thread2_acquires_lock: Thread2 acquires lock "rd_kafka_toppar_s.rktp_lock".
4. rdkafka_partition.c: thread2_modifies_field: Thread2 sets "rktp_wait_consumer_lag_resp" to a new value. Note that this write can be reordered at runtime to occur before instructions that do not access this field within this locked region. After Thread2 leaves the critical section, control is switched back to Thread1.
5. rdkafka_partition.c: thread1_acquires_lock: Thread1 acquires lock "rd_kafka_toppar_s.rktp_lock".
6. rdkafka_partition.c: thread1_overwrites_value_in_field: Thread1 sets "rktp_wait_consumer_lag_resp" to a new value. Now the two threads have an inconsistent view of "rktp_wait_consumer_lag_resp" and updates to fields correlated with "rktp_wait_consumer_lag_resp" may be lost.
7. rdkafka_partition.c: use_same_locks_for_read_and_modify: Guard the modification of "rktp_wait_consumer_lag_resp" and the read used to decide whether to modify "rktp_wait_consumer_lag_resp" with the same set of locks.
# }
#
# 155|-> rktp->rktp_wait_consumer_lag_resp = 1;
# 156|
# 157| partitions = rd_kafka_topic_partition_list_new(1);
Second - rd_kafka_broker_monitor_del():
1. rdkafka_broker.c: assign: Assigning: "rkb" = "rkbmon->rkbmon_rkb".
2. rdkafka_broker.c: thread1_reads_field: Thread1 reads the field "rkbmon_rkb".
3. rdkafka_broker.c thread1_checks_field: Thread1 uses the value read from field "rkbmon_rkb" in the condition "!rkb". It sees that the condition is false. Control is switched to Thread2.
4. rdkafka_broker.c: thread2_reads_field: Thread2 reads the field "rkbmon_rkb".
5. rdkafka_broker.c: thread2_checks_field: Thread2 uses the value read from field "rkbmon_rkb" in the condition "!rkb". It sees that the condition is false.
6. rdkafka_broker.c: thread2_acquires_lock: Thread2 acquires lock "rd_kafka_broker_s.rkb_lock".
7. rdkafka_broker.c: thread2_modifies_field: Thread2 sets "rkbmon_rkb" to a new value. Note that this write can be reordered at runtime to occur before instructions that do not access this field within this locked region. After Thread2 leaves the critical section, control is switched back to Thread1.
8. rdkafka_broker.c: thread1_acquires_lock: Thread1 acquires lock "rd_kafka_broker_s.rkb_lock".
9. rdkafka_broker.c: thread1_overwrites_value_in_field: Thread1 sets "rkbmon_rkb" to a new value. Now the two threads have an inconsistent view of "rkbmon_rkb" and updates to fields of "rkbmon_rkb" or fields correlated with "rkbmon_rkb" may be lost.
10. rdkafka_broker.c: use_same_locks_for_read_and_modify: Guard the modification of "rkbmon_rkb" and the read used to decide whether to modify "rkbmon_rkb" with the same set of locks.
# 5963|
# 5964| rd_kafka_broker_lock(rkb);
# 5965|-> rkbmon->rkbmon_rkb = NULL;
# 5966| rd_kafka_q_destroy(rkbmon->rkbmon_q);
# 5967| TAILQ_REMOVE(&rkb->rkb_monitors, rkbmon, rkbmon_link);
Checklist
Please provide the following information:
- [x] librdkafka version (release number or git tag):
<v2.3.0> - [x] Apache Kafka version:
<3.6> - [x] librdkafka client configuration:
<not needed here> - [x] Operating system:
<Fedora 38> - [x] Provide logs (with
debug=..as necessary) from librdkafka - [x] Provide broker log excerpts - not needed
- [x] Critical issue - it's been part of librdkafka for a while, so I don't think it's critical