COVESA / capicxx-someip-runtime

Common API C++ SOMEIP runtime
Mozilla Public License 2.0
111 stars 82 forks source link

Deserialization issues with 3.2.3-r8 #36

Open kheaactua opened 10 months ago

kheaactua commented 10 months ago

I haven't been able to narrow down the exact cause yet, but with 3.2.3-r8 I'm seeing seserialization issues. Not 100% of the time, but 100% reproducible. I'm trying to build a minimal example now that exposes the issue.

Has any one else seen this?

In this hard to read log where I filled the serialization/deserialization with debug:

foo      main   [foo.tokenUpdateProxy] readCpToken(): (154) m_pProxy->transferRequestFromApp(ETransferMessageId(uint16) msgId=ReadInitRequest=65333 (65333 <= 65535), UInt16 transactionIdentifier=55, ByteBuffer requestData=[])
foo commonapi   OutputStream.hpp:97 writeValue<uint8_t>
foo commonapi   OutputStream.hpp:487 _writeBitValue(val=0x5=5, nbits=8, is_signed=0)
foo commonapi   OutputStream.hpp:107 writeValue<uint16_t>
foo commonapi   OutputStream.hpp:487 _writeBitValue(val=0x37=55, nbits=16, is_signed=0)
foo commonapi   OutputStream.hpp:487 _writeBitValue(val=0x0=0, nbits=32, is_signed=0)
foo commonapi   callMethodWithReply REMOTE_ERROR!

bar commonapi   InputStream.cpp:144 readValue<uint16_t>
bar commonapi   InputStream.hpp:546 _readBitValue(65332, 16, 0), isLittleEndian=false
bar commonapi   deserialize (2)
bar commonapi   InputStream.cpp:144 readValue<uint16_t>
bar commonapi   InputStream.hpp:546 _readBitValue(0, 16, 0), isLittleEndian=false
bar commonapi   deserialize (2)
bar commonapi   InputStream.cpp:337 readValue
bar commonapi   InputStream.cpp:197 readValue
bar commonapi   InputStream.hpp:546 _readBitValue(337, 32, 0), isLittleEndian=false
bar commonapi   InputStream.hpp:559 _readBitValue failed sanity check: _bits = 32, remaining_ = 3 <? size_t(((_bits - 1) >> 3) + 1)=4
bar commonapi   deserialize (1)
bar commonapi   MethodWithReplyStubDispatcher (someip): deserialization failed! [0413:<bar.TokenUpdate>.22155.15500:<m:transferRequestFromApp>.64]

You can see that the 65333 is written as 5

This happens 100% at this call, but there are other calls where serialization/deserialization is fine.

One particular pattern that coordinates with this is when proxy calls are in callbacks (which emits a BLOCKING CALL AVAILABLITY vsomeip warning)

i.e.

proxy->getProxyStatusEvent().subscribe(
    [](auto const& /* availability_status */) {
       proxy->someOtherCall();
    }
);

this is a bad pattern and I'm trying to get rid of it anyways, BUT:

  1. This didn't cause problems with 3.2.0
  2. Fixing this doesn't resolve the deserialization issues, but my gut feeling is that it is somewhat related.

In the mean time, I've had to modify 3.2.0 to be compatible with vsomeip 3.4.10 and the 3.1.14 generators (basically change uid/gid for sec_client_t)

kheaactua commented 10 months ago

To follow up here, I see this on all non uint8_t enums. First, even with the 3.2.14 generators, to use a non uint8_t enum one must still re-run the core generator after the someip generator (as suggested in https://github.com/COVESA/capicxx-core-tools/issues/32), but regardless OutputStream.hpp on the stub end still gets a null deployment object and assumes an uint8_t and cannot properly deserialize.

My test setup has:

// fidl
interface CapicxxExample {
  version {major 1 minor 0}

  method getColor {
    out {
      ExampleTypes.Color color
    }
  }

  method setColor {
    in {
      ExampleTypes.Color color
    }
    error ExampleTypes.ErrorTypeEnum
  }
}

typeCollection ExampleTypes {
  version {major 1 minor 0}

  enumeration ErrorTypeEnum {
    Ok
    Failed
  }

  enumeration Color {
    Red = 1111
    Green = 2222
    Blue = 3333
    Teal = 4444
  }
}
import "platform:/plugin/org.genivi.commonapi.someip/deployment/CommonAPI-4-SOMEIP_deployment_spec.fdepl"
import "platform:/plugin/org.genivi.commonapi.core/deployment/CommonAPI-4_deployment_spec.fdepl"

import "capicxx-example.fidl"

define org.genivi.commonapi.core.deployment for typeCollection example.ExampleTypes {
  enumeration Color {
    EnumBackingType = UInt32
  }
}

define org.genivi.commonapi.someip.deployment for interface example.CapicxxExample {
  method getColor {
    SomeIpMethodID                  = 1 // 0x0001
    SomeIpReliable                  = true
  }

  method setColor {
    SomeIpMethodID                  = 2 // 0x0002
    SomeIpReliable                  = true
  }
}

And while the type is correct in core/common/v1/example/ExampleTypes.hpp, i.e.

    struct Color : CommonAPI::Enumeration< uint32_t> {
        enum Literal : uint32_t {
            Red = 1111,
            Green = 2222,
            Blue = 3333,
            Teal = 4444
        };

It still fails the deserialization. I'm curious if it's because the uint8_t in someip/common/v1/example/ExampleTypesSomeIPDeployment.hpp

typedef CommonAPI::SomeIP::EnumerationDeployment<uint8_t> ColorDeployment_t;

I don't have a good grasp on the deployment types yet so this is taking a while to get to the bottom of.