cPacket causing simulation crash in OMNet++ - omnet++

I have defined 2 cPackets msg files as:
packet MyLinkFrame {
int f1;
int f2;
}
and
packet IPv4ARPTotf {
string SourceIP;
string DestinationIP;
}
Then in my simulation, one network node receives the linklayer frame MyLinkFrame is received which encapsulates IPv4ARPTotf.
Then, on the receiving network node I create a new ARP Reply packet of IPv4ARPTotf type as follows:
if(check_for_validity(static_cast<IPv4ARPTotf *>(MyLinkFrame->decapsulate())))
{
if (MyLinkFrame->getFrameType() == 0) {
tempIPARPRequest = static_cast<IPv4ARPTotf *>(MyLinkFrame->decapsulate());
tempIPARPReply = new IPv4ARPTotf("IPv4ARPReply");
tempIPARPReply->setSourceIP(tempIPARPRequest->getDestinationIP());
tempIPARPReply->setDestinationIP(tempIPARPRequest->getSourceIP());
}
}
Now it is crashing for lines inside the inner if block.

You are decapsulating the received frame two times.
Once in the function call of check_for_validity() and another inside the if block whenever the if condition passes. So inside the if block when you try to decapsulate() it again then a null pointer is returned. Hence, when you try to access parameters tempIPARPRequest->getDestinationIP() of this null object you get an exception and your simulation crashes.
An easy fix would be to pass a duplicate object to your check_for_validity() function and optionally delete the dulicated msg inside that function.
Sample modification of your supplied code:
if(check_for_validity(static_cast<IPv4ARPTotf *>(MyLinkFrame->dup()->decapsulate())))
{
if (MyLinkFrame->getFrameType() == 0) {
tempIPARPRequest = static_cast<IPv4ARPTotf *>(MyLinkFrame->decapsulate());
tempIPARPReply = new IPv4ARPTotf("IPv4ARPReply");
tempIPARPReply->setSourceIP(tempIPARPRequest->getDestinationIP());
tempIPARPReply->setDestinationIP(tempIPARPRequest->getSourceIP());
}
}

Related

How to receive messages via wifi while running main program in ESP32?

Ive incorporated multiple features i want in a microcontroller program (ESP32 Wroom32) and needed some advice on the best way to keep the program running and receive messages while it is running.
Current code:
//includes and declarations
setup()
{
//setup up wifi, server
}
main(){
WiFiClient client = server.available();
byte new_command[40];
if (client) // If client object is created, a connection is setup
{
Serial.println("New wifi Client.");
String currentLine = ""; //Used to print messages
while (client.connected())
{
recv_byte = client.read();
new_command = read_incoming(&recv_byte, client); //Returns received command and check for format. If invalid, returns a 0 array
if (new_command[0] != 0) //Checks if message is not zero, None of valid messages start with zero
{
execute_command(new_command);
//new_command is set to zero
}
}//end of while loop
}//end of if loop
}
The downside of this is that the ESP32 waits till the command is finished executing before it is ready to receive a new message. It is desired that the ESP32 receive commands and store them, and execute it at its own pace. I am planning to change the current code to receive a messages while the code is running as follows:
main()
{
WiFiClient client = server.available();
byte new_command[40];
int command_count = 0;
byte command_array[50][40];
if (command_count != 0)
{
execute_command(command_array[0]);
//Decrement command_count
//Shift all commands in command_array by 1 row above
//Set last executed command to zero
}
}//end of main loop
def message_interrupt(int recv_byte, WiFiClient& running_client)
{
If (running_client.connected())
{
recv_byte = running_client.read();
new_command = read_incoming(&recv_byte, running_client); //Returns received command and check for format. If invalid, returns a 0 array
//add new command to command_array after last command
//increment command_count
}
}
Which interrupt do I use to receive the message and update the command_array ? https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html Doesnt mention any receive/transmit events. I couldnt find any receive/transmit interrupt either or maybe I searched for the wrong term.

From my understanding this lambda call should be invalid, but it does not crash. Why?

I am having trouble understanding why the following code does not crash.
class MyClass
{
public:
MyClass() { m_contents = 0xF0F0F0F0; }
void Hello() { printf("Hello, address: %llx, contents: %x, size: %d\n", (long long int)this, m_contents, sizeof(MyClass)); }
int m_contents;
};
int main()
{
MyClass* MyObj = new MyClass();
MyObj->Hello();
auto MyLambda = [MyObj]()
{
if (MyObj != nullptr)
{
MyObj->Hello();
}
};
memset(MyObj, 0, sizeof(MyClass));
MyObj->Hello();
delete MyObj;
MyObj = nullptr;
MyLambda();
return 0;
}
This is the output:
Hello, address: 1ddb4a16100, contents: f0f0f0f0, size: 4
Hello, address: 1ddb4a16100, contents: 0, size: 4
Hello, address: 1ddb4a16100, contents: dddddddd, size: 4
I would have expected the lambda call to crash because I wiped out all the memory that it is using to call the Hello() function. I know the contents are wiped because m_contents becomes 0. After calling delete, m_contents becomes a random value, but still, Hello() is called and there is no crash.
Follow up question:
In a lambda where I pass this as a capture, is there a chance that this becomes null or invalid by the time the lambda is called?
[MyObj]() { } does not capture the pointer MyObj by reference, but by value. That means that the value of MyObj will be copied at the time of creation of the lambda. So even after you set MyObj to nullptr, the lambda will still use its original value, which still points to the same area in memory.
At the time you call the lambda, the object at *MyObj has already been deleted, which can be seen by all the 0xdd bytes (at least in Debug mode).
If you were to write [&MyObj]() { } then MyObj would be captured as a reference, meaning the lambda will always use the current value of the captured pointer. In that case, the behavior should be exactly as you expected in the first place: the nullptr check in your lambda would fail and Hello() would not be called.
As for your follow up question: Passing this does work no different than any other symbol. Passing it by value will create a copy which will always allow you access to the object, even after its lifetime (with all the risks resulting from that). Passing it by reference will work as long the this pointer is valid, which will probably be as long as the scope of the method is valid.

rw_semaphore's negative count value

I am debugging a kernel crash dump. There seems to be a problem with one process was trying to memory map a new region. The problem is that it was not able to hold the memory map semaphore.
When I looked into process's mm_struct and printed its content. I saw that the struct rw_semaphore mmap_sem were as seen below. Now, does he value of count seem suspicious? It has a negative value, as if there was a race condition where it was decremented twice by two different threads after checking for zero.
mmap_sem = {
count = -4294967295,
wait_lock = {
{
rlock = {
raw_lock = {
slock = 262148
}
}
}
},
wait_list = {
next = 0xffff8801f0113e48,
prev = 0xffff8801f0113e48
}
},
Sorry for the confusion. I thought crash pulls the correct data types and uses that properly when printing out the all the values ...
Looks like crash utility is not read the count member as an int ....
When I print it as int, I get the correct value.
crash> p (int) (((struct mm_struct *) 0xffff8801f15fa540)->mmap_sem).count
$13 = 1

C# : this.Invoke((MethodInvoker)delegate

can somebody explain me the following code please :
this.Invoke((MethodInvoker)delegate
{
lblNCK.Text = cncType;
});
Here is where it comes from :
string cncType;
if (objDMainCncData != null)
{
int rc = objDMainCncData.Init(objDGroupManager.Handle);
if (rc == 0)
{
cncType = objDMainCncData.GetCncIdentifier();
if (cncType != string.Empty)
{
if (cncType.ToUpper().IndexOf("+") != -1)
_bFXplus = true;
this.Invoke((MethodInvoker)delegate
{
lblNCK.Text = cncType;
});
}
}
else
{
DisplayMessage("objDMainCncData.Init() failed ! error : " + rc.ToString());
}
}
}
I don't get the use of "this.Invoke((MethodInvoker)delegate".
Thank you by advance.
Peter.
Strange that no one has answered this.
Lets take it in pieces:
this.Invoke: This is a synchronization mechanism, contained in all controls. All graphic/GUI updates, must only be executed from the GUI thread. (This is most likely the main thread.) So if you have other threads (eg. worker threads, async functions etc.) that will result in GUI updates, you need to use the Invoke. Otherwise the program will blow up.
delegate{ ... }: This is a anonymous function. You can think of it as "creating a function on the fly". (Instead of finding a space in the code, create function name, arguments etc.)
(MethodInvoker): The MethodInvoker is just the name of the delegate, that Invoke is expecting. Eg. Invoke expects to be given a function, with the same signature as the "MethodInvoker" function.
What happens, is that Invoke is given a function pointer. It wakes up the GUI thread through a mutex and tells it to executes the function (through the function pointer). The parent thread then waits for the GUI thread to finish the execution. And it's done.

modify captured array c++11 lambda function

I'm writing an Windows phone application with C++/CX. The function tries to copy input array to output array asynchronously:
IAsyncAction CopyAsync(const Platform::Array<byte, 1>^ input, Platform::WriteOnlyArray<byte, 1>^ output)
{
byte *inputData = input->Data;
byte *outputData = output->Data;
int byteCount = input->Length;
// if I put it here, there is no error
//memcpy_s(outputData, byteCount, inputData, byteCount);
return concurrency::create_async([&]() -> void {
memcpy_s(outputData, byteCount, inputData, byteCount); // access violation exception
return;
});
}
This function compiles but cannot run correctly and produces an "Access violation exception". How can I modify values in the output array?
This is Undefined Behaviour: by the time you use your 3 captured (by reference) variables inputData/outputData/byteCount in the lambda, you already returned from CopyAsync and the stack has been trashed.
It's really the same issue as if you returned a reference to a local variable from a function (which we know is evil), except that here the references are hidden inside the lambda so it's a bit harder to see at first glance.
If you are sure that input and output won't change and will still be reachable between the moment you call CopyAsync and the moment you run the asynchronous action, you can capture your variables by value instead of by reference:
return concurrency::create_async([=]() -> void {
// ^ here
memcpy_s(outputData, byteCount, inputData, byteCount);
return;
});
Since they're only pointers (and an int), you won't be copying the pointed-to data, only the pointers themselves.
Or you could just capture input and output by value: since they're garbage-collected pointers this will at least make sure the objects are still reachable by the time you run the lambda:
return concurrency::create_async([=]() -> void {
memcpy_s(output->Data, input->Length, input->Data, input->Length);
return;
});
I for one prefer this second solution, it provides more guarantees (namely, object reachability) than the first one.

Resources