Issue 135117
Summary Inaccurate Coverage Information Due to __llvm_profile_dump During Program Blocking, Requesting Solution
Labels new issue
Assignees
Reporter Kurtcobainzl
    I have created a demo to investigate coverage collection, and I've observed that the code coverage information for the code located after a blocking operation (such as sleep, scanf, etc.) is inaccurate when `__llvm_profile_dump` is executed while the program is blocked. Below are the details of my experiment and environment information. I would appreciate guidance and potential solutions to this issue.
**Environment Information:**
`clang --version
Homebrew clang version 20.1.1
Target: arm64-apple-darwin24.2.0
Thread model: posix
InstalledDir: /opt/homebrew/Cellar/llvm/20.1.1/bin
Configuration file: /opt/homebrew/etc/clang/arm64-apple-darwin24.cfg

 llvm-cov --version
Homebrew LLVM version 20.1.1
Optimized build.`

Demo Code:

`
#include <stdint.h>
#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <signal.h>
#include <atomic>
#include <fstream>
#include <limits>
#include <iostream>


extern "C" void __llvm_profile_reset_counters(void);
extern "C" int __llvm_profile_dump(void);


std::atomic<bool> keep_running(true);


void* profile_dumper_thread(void* arg) {
    while (keep_running) {
        sleep(5);
        printf("\n[Background Thread] Dumping coverage data...\n");
        __llvm_profile_dump();
 __llvm_profile_reset_counters();
    }
    return nullptr;
}

void foo() {
    printf("foo() running\n");
}

void conditional_function(int value) {
    printf("conditional_function() running, value = %d\n", value);
    if (value > 10) {
        printf("value > 10\n");
    } else {
        printf("value <= 10\n");
    }
}

int main() {
 printf("Hello, SanitizerCoverage!\n");
    int choice1 = 1;
    if (choice1 == 1) {
        printf("hello1");
    } else {
 printf("world1");
    }
    // Create background thread
    pthread_t thread_id;
    if (pthread_create(&thread_id, nullptr, profile_dumper_thread, nullptr) != 0) {
        perror("Failed to create background thread");
        return 1;
    }
    printf("\nProgram will block, waiting for input...\n");
    // conditional_function(15);
// std::cin.get();
    sleep(5);
    conditional_function(15);

 sleep(5);
    int choice2 = 2;
    if (choice2 == 2) {
 printf("hello2");
    } else {
        printf("world2");
    }

 sleep(5);
    int choice3 = 3;
    if (choice3 == 3) {
 printf("hello3");
    } else {
        printf("world3");
    }

 sleep(5);
    int choice4 = 4;
    if (choice4 == 4) {
 printf("hello4");
    } else {
        printf("world4");
    }

 sleep(5);
    int choice5 = 5;
    if (choice5 == 5) {
 printf("hello5");
    } else {
        printf("world5");
    }

 sleep(5);
    int choice6 = 6;
    if (choice6 == 6) {
 printf("hello6");
    } else {
        printf("world6");
    }


 sleep(5);
    int choice7 = 7;
    if (choice7 == 7) {
 printf("hello7");
    } else {
        printf("world7");
    }

 sleep(5);
    int choice8 = 8;
    if (choice8 == 8) {
 printf("hello8");
    } else {
        printf("world8");
    }

 sleep(5);
    int choice9 = 9;
    if (choice9 == 9) {
 printf("hello9");
    } else {
        printf("world9");
    }

 sleep(5);
    int choice10 = 10;
    if (choice10 == 10) {
 printf("hello10");
    } else {
        printf("world10");
    }
 return 0;
}
`
**Execution Process:**

First Execution:

1. Build the executable: `clang++ -fprofile-instr-generate -fcoverage-mapping -mllvm -runtime-counter-relocation demo06.cpp -o demo`
2. Run the executable: `./demo`
3. Wait for a while, but do not let the program finish naturally.
4. Execute the command `llvm-profdata merge -sparse default.profraw -o default.profdata`. At this point, the coverage information has been translated into the default.profdata file. You can terminate the running program.
5. Execute the command `llvm-cov show ./demo -instr-profile="" --show-line-counts-or-regions` to view the coverage information.

![Image](https://github.com/user-attachments/assets/a7cc7858-ceed-4193-b370-3de6ae4da176)

![Image](https://github.com/user-attachments/assets/171a5d90-d0e5-42c5-9621-e7fceb270845)

![Image](https://github.com/user-attachments/assets/3be6ee4a-4672-4e68-8e2e-fc80e6ff20f1)

You can observe that the coverage information before line 79 is correct, but after line 79, although none of the code is actually executed, a significant portion of the code is marked as executed.

Second Execution:

Clear the files generated during the first execution. Repeat the steps of the first execution, but this time, allow the program to finish naturally before collecting the coverage. You will see that the coverage information is accurate.

![Image](https://github.com/user-attachments/assets/a7bc02be-5356-4639-b727-1dd031208c3d)

![Image](https://github.com/user-attachments/assets/573b84de-4fe5-45fe-ac6f-dcb9c058ad89)

I suspect that the blocking execution is causing the subsequent code coverage to fail to be recorded correctly when `__llvm_profile_dump` is called during the blocked state. I hope the official team can clarify my doubts. If possible, I would appreciate any guidance on how to accurately obtain C++ coverage information in such scenarios.




_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to