Skip to content

[BUG]: Multi Event Communication failure #1019

@manikanta21296-source

Description

@manikanta21296-source

vSomeip Version

3.4.10

Boost Version

1.71

Environment

Embedded Linux

Describe the bug

Same Machine behavior.

Use Case Description

There are two Adaptive AUTOSAR applications communicating via SOME/IP (vSomeIP).
Both applications use:

Same Service ID
Same Instance ID
One Event Group ID
10 Event IDs belonging to that single event group

Roles

Provider application

Acts as SOME/IP service provider

Consumer application

Acts as SOME/IP service consumer
Uses dynamic discovery

Provider Behavior

Provider application startup sequence is:

Calls offer_service(service_id, instance_id)
Calls offer_event(...) individually for 10 events (same event group)

offer_event() calls for all events are not done atomically and take place sequentially after offer_service()

Consumer Behavior

Consumer application startup sequence:

Consumer starts first
Registers:

register_availability_handler() (dynamic discovery)

Calls:

request_service(service_id, instance_id)

When the provider becomes available, the following happens inside the availability callback:

request_event() is called for all 10 events
subscribe(service_id, instance_id, eventgroup_id) is called
Consumer waits for subscription acknowledgment (SUBSCRIBE_ACK)

Observed Problem

When the consumer starts before the provider:

Consumer waits for availability callback
Once the provider starts, the availability callback is triggered correctly

At this point:

Provider has called offer_service()
Not all offer_event() calls have been completed yet

Despite this:

Subscription is acknowledged successfully to the consumer

After subscription acknowledgment:

Remaining offer_event() calls are executed on the provider side

When the provider sends event data:

✅ Events that were offered before subscription acknowledgment are received correctly
❌ Events that were offered after subscription acknowledgment:

Data is not delivered to the consumer
No event notification is received for those events

Reproduction Steps

Run two applications by compiling the attached sources one for provider and one for consumer.

Expected behaviour

Subscription acknowledgment should be sent only after:

Service is offered and
All events belonging to the subscribed event group are fully offered

OR
Events offered after subscription acknowledgment should still:

Be correctly associated with the existing subscription
Deliver event data to the consumer

Actual Behavior

Subscription acknowledgment is sent even when only a subset of events is offered
Events offered after acknowledgment never deliver data to the consumer
This leads to partial event reception despite successful subscription

Impact

Causes loss of event notifications
Behavior is timing‑dependent
Reproducible only when:

Consumer starts first
Provider offers events incrementally after offer_service()

Logs and Screenshots

Sender.cpp
`#include <vsomeip/vsomeip.hpp>

#include
#include
#include
#include
#include
#include
#include
#include
#include

namespace ids {
static constexpr vsomeip::service_t SERVICE = 0x1234;
static constexpr vsomeip::instance_t INSTANCE = 0x5678;

static constexpr int NUM_EVENTS = 10;

static constexpr vsomeip::event_t EVENTS[NUM_EVENTS] = {
    0x8001, 0x8002, 0x8003, 0x8004, 0x8005,
    0x8006, 0x8007, 0x8008, 0x8009, 0x800A
};

static constexpr vsomeip::eventgroup_t EVENTGROUPS[NUM_EVENTS] = {
    0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
    0x0001, 0x0001, 0x0001, 0x0001, 0x0001
};

}

class provider_app {
public:
provider_app()
: app_(vsomeip::runtime::get()->create_application("provider")),
running_(true),
offered_(false) {}

bool init() {
    if (!app_->init()) {
        std::cerr << "provider: app_->init() failed\n";
        return false;
    }

    app_->register_state_handler(
        std::bind(&provider_app::on_state, this, std::placeholders::_1));

    // (Optional) handle method requests if you add methods later:
    // app_->register_message_handler(ids::SERVICE, ids::INSTANCE, vsomeip::ANY_METHOD, ...);

    return true;
}

void start() {
    notify_thread_ = std::thread([this] { notify_loop(); });
    app_->start();
}

void stop() {
    running_ = false;
    if (notify_thread_.joinable()) notify_thread_.join();

    if (offered_) {
        // Stop offering events + service
        for (int i = 0; i < ids::NUM_EVENTS; ++i) {
            app_->stop_offer_event(ids::SERVICE, ids::INSTANCE, ids::EVENTS[i]);
        }
        app_->stop_offer_service(ids::SERVICE, ids::INSTANCE);
    }

    app_->clear_all_handler();
    app_->stop();
}

private:
void on_state(vsomeip::state_type_e st) {
if (st != vsomeip::state_type_e::ST_REGISTERED)
return;

    app_->offer_service(ids::SERVICE, ids::INSTANCE); // [1](https://github.com/COVESA/vsomeip/blob/master/interface/vsomeip/application.hpp)
    offered_ = true;

    // Offer 10 events (each in its own eventgroup)
    for (int i = 0; i < ids::NUM_EVENTS; ++i) {
        std::set<vsomeip::eventgroup_t> groups{ ids::EVENTGROUPS[i] };

        // offer_event signature (service, instance, notifier/event, eventgroups, type, cycle, ...)
        // Type = ET_EVENT (no caching). [1](https://github.com/COVESA/vsomeip/blob/master/interface/vsomeip/application.hpp)
        app_->offer_event(
            ids::SERVICE,
            ids::INSTANCE,
            ids::EVENTS[i],
            groups,
            vsomeip::event_type_e::ET_EVENT,
            std::chrono::milliseconds::zero(),   // no periodic resend by middleware
            false,                                // change_resets_cycle
            true,                                 // update_on_change
            nullptr,                               // epsilon_change_func
            vsomeip::reliability_type_e::RT_UNKNOWN
        );
    }

    // Offer the service instance
    
    std::cout << "provider: offered service "
              << std::hex << ids::SERVICE << "." << ids::INSTANCE
              << " with " << std::dec << ids::NUM_EVENTS << " events\n";
}

void notify_loop() {
    uint32_t counter = 0;

    while (running_) {
        // Create payload once per event
        for (int i = 0; i < ids::NUM_EVENTS; ++i) {
            auto pl = vsomeip::runtime::get()->create_payload();

            // Simple payload: [event_index, counter bytes...]
            std::vector<vsomeip::byte_t> data;
            data.push_back(static_cast<vsomeip::byte_t>(i));
            data.push_back(static_cast<vsomeip::byte_t>((counter >> 0) & 0xFF));
            data.push_back(static_cast<vsomeip::byte_t>((counter >> 8) & 0xFF));
            data.push_back(static_cast<vsomeip::byte_t>((counter >> 16) & 0xFF));
            data.push_back(static_cast<vsomeip::byte_t>((counter >> 24) & 0xFF));

            pl->set_data(data);

            // notify(service, instance, event, payload) [1](https://github.com/COVESA/vsomeip/blob/master/interface/vsomeip/application.hpp)
            app_->notify(ids::SERVICE, ids::INSTANCE, ids::EVENTS[i], pl);
        }

        ++counter;
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
}

private:
std::shared_ptrvsomeip::application app_;
std::atomic running_;
std::atomic offered_;
std::thread notify_thread_;
};

static provider_app* g_app = nullptr;

static void handle_signal(int sig) {
if (g_app && (sig == SIGINT || sig == SIGTERM)) {
g_app->stop();
}
}

int main() {
provider_app app;
g_app = &app;

std::signal(SIGINT, handle_signal);
std::signal(SIGTERM, handle_signal);

if (!app.init()) return 1;
app.start();
return 0;

}`

`#include <vsomeip/vsomeip.hpp>

#include
#include
#include
#include
#include
#include
#include

namespace ids {
static constexpr vsomeip::service_t SERVICE = 0x1234;
static constexpr vsomeip::instance_t INSTANCE = 0x5678;

static constexpr int NUM_EVENTS = 10;

static constexpr vsomeip::event_t EVENTS[NUM_EVENTS] = {
    0x8001, 0x8002, 0x8003, 0x8004, 0x8005,
    0x8006, 0x8007, 0x8008, 0x8009, 0x800A
};

static constexpr vsomeip::eventgroup_t EVENTGROUPS[NUM_EVENTS] = {
    0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
    0x0001, 0x0001, 0x0001, 0x0001, 0x0001
};

}

class consumer_app {
public:
consumer_app()
: app_(vsomeip::runtime::get()->create_application("consumer")),
subscribed_(false) {}

bool init() {
    if (!app_->init()) {
        std::cerr << "consumer: app_->init() failed\n";
        return false;
    }

    app_->register_state_handler(
        std::bind(&consumer_app::on_state, this, std::placeholders::_1));

    app_->register_availability_handler(
        ids::SERVICE, ids::INSTANCE,
        std::bind(&consumer_app::on_availability, this,
                  std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); // [2](https://github.com/COVESA/vsomeip/blob/master/examples/subscribe-sample.cpp)

    // Receive all notifications (events come as method IDs in SOME/IP messages)
    app_->register_message_handler(
        ids::SERVICE, ids::INSTANCE, vsomeip::ANY_METHOD,
        std::bind(&consumer_app::on_message, this, std::placeholders::_1)); // sample pattern [2](https://github.com/COVESA/vsomeip/blob/master/examples/subscribe-sample.cpp)

    return true;
}

void start() { app_->start(); }

void stop() {
    // Unsubscribe + release
    if (subscribed_) {
        for (int i = 0; i < ids::NUM_EVENTS; ++i) {
            app_->unsubscribe(ids::SERVICE, ids::INSTANCE, ids::EVENTGROUPS[i]); // [1](https://github.com/COVESA/vsomeip/blob/master/interface/vsomeip/application.hpp)
            app_->release_event(ids::SERVICE, ids::INSTANCE, ids::EVENTS[i]);   // [1](https://github.com/COVESA/vsomeip/blob/master/interface/vsomeip/application.hpp)
        }
        app_->release_service(ids::SERVICE, ids::INSTANCE); // [1](https://github.com/COVESA/vsomeip/blob/master/interface/vsomeip/application.hpp)
    }

    app_->clear_all_handler();
    app_->stop();
}

private:
void on_state(vsomeip::state_type_e st) {
if (st == vsomeip::state_type_e::ST_REGISTERED) {
// Express interest in the service (dynamic discovery happens afterwards)
app_->request_service(ids::SERVICE, ids::INSTANCE); // 12
std::cout << "consumer: requested service "
<< std::hex << ids::SERVICE << "." << ids::INSTANCE << "\n";
}
}

void on_availability(vsomeip::service_t svc,
                     vsomeip::instance_t inst,
                     bool is_available) {
    std::cout << "consumer: service ["
              << std::hex << svc << "." << inst << "] is "
              << (is_available ? "available" : "NOT available") << "\n"; // sample prints [2](https://github.com/COVESA/vsomeip/blob/master/examples/subscribe-sample.cpp)

    if (!is_available || subscribed_) return;

    // Once discovered: request_event(10) then subscribe(10).
    // vSomeIP requires request_event before subscribe. [1](https://github.com/COVESA/vsomeip/blob/master/interface/vsomeip/application.hpp)
    for (int i = 0; i < ids::NUM_EVENTS; ++i) {
        std::set<vsomeip::eventgroup_t> groups{ ids::EVENTGROUPS[i] };

        app_->request_event(
            ids::SERVICE,
            ids::INSTANCE,
            ids::EVENTS[i],
            groups,
            vsomeip::event_type_e::ET_EVENT,
            vsomeip::reliability_type_e::RT_UNKNOWN
        ); // [1](https://github.com/COVESA/vsomeip/blob/master/interface/vsomeip/application.hpp)
    }

        app_->subscribe(ids::SERVICE, ids::INSTANCE, ids::EVENTGROUPS[0]); // [1](https://github.com/COVESA/vsomeip/blob/master/interface/vsomeip/application.hpp)[2](https://github.com/COVESA/vsomeip/blob/master/examples/subscribe-sample.cpp)

    subscribed_ = true;
    std::cout << "consumer: requested 10 events and subscribed to 10 eventgroups\n";
}

void on_message(const std::shared_ptr<vsomeip::message>& msg) {
    // For notifications, get_method() carries the event id (notifier id)
    std::stringstream ss;
    ss << "consumer: notif ["
       << std::hex << std::setw(4) << std::setfill('0')
       << msg->get_service() << "."
       << std::setw(4) << msg->get_instance() << "."
       << std::setw(4) << msg->get_method() << "] payload=";

    auto pl = msg->get_payload();
    ss << "(" << std::dec << pl->get_length() << ") ";
    for (uint32_t i = 0; i < pl->get_length(); ++i)
        ss << std::hex << std::setw(2) << (int)pl->get_data()[i] << " ";

    std::cout << ss.str() << "\n";
}

private:
std::shared_ptrvsomeip::application app_;
std::atomic subscribed_;
};

static consumer_app* g_app = nullptr;

static void handle_signal(int sig) {
if (g_app && (sig == SIGINT || sig == SIGTERM)) {
g_app->stop();
}
}

int main() {
consumer_app app;
g_app = &app;

std::signal(SIGINT, handle_signal);
std::signal(SIGTERM, handle_signal);

if (!app.init()) return 1;
app.start();
return 0;

}
`

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions