| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include <iostream> | ||
| 2 | #include <thread> | ||
| 3 | #include <chrono> | ||
| 4 | #include <signal.h> | ||
| 5 | #include <zmq.hpp> | ||
| 6 | #include <unistd.h> | ||
| 7 | #include "data_stream_assert.h" | ||
| 8 | |||
| 9 | // Signal handler function (C style, not lambda) | ||
| 10 | volatile sig_atomic_t signal_received = 0; | ||
| 11 | 1 | void sigusr1_handler(int signum) { | |
| 12 | 1 | signal_received = 1; | |
| 13 | // No std::cout in signal handler - can cause crash! | ||
| 14 | 1 | } | |
| 15 | |||
| 16 | // Test 1: EINTR - Simple test that zmq::poll() returns EINTR when interrupted by signal | ||
| 17 | 1 | void test_eintr(zmq::context_t& context) { | |
| 18 |
2/2✓ Branch 0 (2→3) taken 1 times.
✓ Branch 2 (3→4) taken 1 times.
|
1 | std::cout << "\n1. Test EINTR using zmq::poll() (simple signal interruption test):" << std::endl; |
| 19 | 1 | signal_received = 0; | |
| 20 | 1 | int rc=0; | |
| 21 | |||
| 22 | // Install a handler for SIGALRM that does not restart syscalls | ||
| 23 | struct sigaction old_action; | ||
| 24 | struct sigaction new_action; | ||
| 25 | 1 | new_action.sa_handler = sigusr1_handler; // Use C function, not lambda | |
| 26 | 1 | sigemptyset(&new_action.sa_mask); | |
| 27 | 1 | new_action.sa_flags = 0; // No SA_RESTART to force interruption | |
| 28 | 1 | sigaction(SIGALRM, &new_action, &old_action); | |
| 29 | |||
| 30 | try { | ||
| 31 |
1/1✓ Branch 0 (6→7) taken 1 times.
|
1 | zmq::socket_t req_socket(context, ZMQ_REQ); |
| 32 |
1/1✓ Branch 0 (7→8) taken 1 times.
|
1 | req_socket.connect("tcp://127.0.0.1:5554"); |
| 33 | |||
| 34 |
2/2✓ Branch 0 (8→9) taken 1 times.
✓ Branch 2 (9→10) taken 1 times.
|
1 | std::cout << " Setting up alarm to send SIGALRM in 1 second..." << std::endl; |
| 35 | |||
| 36 | // Use alarm() to send a signal after 1 second - simpler than threads | ||
| 37 | 1 | ualarm(5000, 0); | |
| 38 | |||
| 39 |
2/2✓ Branch 0 (11→12) taken 1 times.
✓ Branch 2 (12→13) taken 1 times.
|
1 | std::cout << " Calling zmq::poll() with infinite timeout..." << std::endl; |
| 40 | |||
| 41 | // Use zmq::poll() - should be interrupted by SIGALRM | ||
| 42 | 1 | zmq::pollitem_t items[] = { {req_socket.handle(), 0, ZMQ_POLLIN, 0} }; | |
| 43 |
0/1✗ Branch 0 (15→16) not taken.
|
1 | rc = zmq::poll(items, 1, std::chrono::milliseconds(-1)); // Block indefinitely |
| 44 |
1/2✗ Branch 0 (41→42) not taken.
✓ Branch 1 (41→43) taken 1 times.
|
2 | } catch (const zmq::error_t& e) { |
| 45 | // Cancel any pending alarm in case of exception | ||
| 46 | 1 | alarm(0); | |
| 47 | |||
| 48 |
7/7✓ Branch 0 (45→46) taken 1 times.
✓ Branch 2 (47→48) taken 1 times.
✓ Branch 4 (48→49) taken 1 times.
✓ Branch 6 (50→51) taken 1 times.
✓ Branch 8 (51→52) taken 1 times.
✓ Branch 10 (52→53) taken 1 times.
✓ Branch 12 (53→54) taken 1 times.
|
1 | std::cout << " Exception caught: " << e.what() << " (code: " << e.num() << ") should be EINTR: " << EINTR << std::endl; |
| 49 |
4/4✓ Branch 0 (56→57) taken 1 times.
✓ Branch 2 (59→60) taken 1 times.
✓ Branch 4 (62→63) taken 1 times.
✓ Branch 6 (64→65) taken 1 times.
|
5 | data_stream_assert(e.num() == EINTR); |
| 50 | 1 | } | |
| 51 | |||
| 52 |
4/4✓ Branch 0 (20→21) taken 1 times.
✓ Branch 2 (23→24) taken 1 times.
✓ Branch 4 (26→27) taken 1 times.
✓ Branch 6 (27→28) taken 1 times.
|
5 | data_stream_assert(rc == 0); |
| 53 | // Restore original signal handler | ||
| 54 | 1 | sigaction(SIGALRM, &old_action, nullptr); | |
| 55 | 1 | } | |
| 56 | |||
| 57 | 1 | int main() { | |
| 58 |
1/1✓ Branch 0 (2→3) taken 1 times.
|
1 | zmq::context_t context(1); |
| 59 | |||
| 60 |
2/2✓ Branch 0 (3→4) taken 1 times.
✓ Branch 2 (4→5) taken 1 times.
|
1 | std::cout << "=== Test error cases when sending ZMQ messages ===" << std::endl; |
| 61 |
1/1✓ Branch 0 (5→6) taken 1 times.
|
1 | test_eintr(context); |
| 62 | |||
| 63 |
2/2✓ Branch 0 (6→7) taken 1 times.
✓ Branch 2 (7→8) taken 1 times.
|
1 | std::cout << "\n✓ All interrupt tests passed" << std::endl; |
| 64 | 1 | return 0; | |
| 65 | 1 | } | |
| 66 |