Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Given a call stack containing a lambda function, how can one determine its source?

Suppose you have some code that pushes onto a queue like this:

template <typename T>
void submitJobToPool(T callable)
{
    someJobQueue.push(callable)
}

...and later on:

template <typename T>
void runJobFromPool(T callable)
{
    auto job = someJobQueue.pop();
    job();
}

Now imagine that the code crashes due to some error inside of the job() call. If the submitted job was a normal function, the call stack might look something like this:

void myFunction()     0x345678901
void runJobFromPool() 0x234567890
int main(int, char**) 0x123456789

It's easy to see what function crashed here. If it's a functor, it'll be similar but with an operator() in there somewhere (ignoring inlining). However, for a lambda...

void lambda_a7009ccf8810b62b59083b4c1779e569() 0x345678901
void runJobFromPool()                          0x234567890
int main(int, char**)                          0x123456789

This is not so easy to debug. If there's a debugger attached when it happens, or a core dump available, then that information can be used to derive which lambda crashed, but that information is not always available. As far as I know, disassembly is one of the few ways to determine what crashed from this.

The ideas I've had to make this better are:

  1. Using a tool like addr2line if the platform supports it. This sometimes works, sometimes not.
  2. Wrapping up all lambdas in functors (not ideal, to say the least).
  3. Not using lambdas (again, not ideal).
  4. Using a compiler extension to give the lambda a more meaningful name / add debugging info.

The 4th option sounded promising, so I did some investigation, but couldn't find anything. In case it matters, the compilers I have available are clang++ 5.0 and MSVC 19 (Visual Studio 2015).

My question is, what other tools / techniques are available that can help map a callstack with a lambda function in it to the corresponding source line?

like image 593
OMGtechy Avatar asked May 17 '18 15:05

OMGtechy


People also ask

How do you see the code in a lambda function?

You can use the code editor in the AWS Lambda console to write, test, and view the execution results of your Lambda function code. The code editor supports languages that do not require compiling, such as Node. js and Python. The code editor suppports only .

Can you call function in lambda?

We can declare a lambda function and call it as an anonymous function, without assigning it to a variable.

How do you call a lambda function from another lambda function in Python?

Let the name of this function be – “ChildFunction” and select Python 3.8 as the runtime. Select the option to Create a new role with basic lambda permissions and click on Create Function. A new lambda function will be created where you can write your code and test it.

How do you call one lambda from another?

Here is the python example of calling another lambda function and gets its response. There is two invocation type 'RequestResponse' and 'Event'. Use 'RequestResponse' if you want to get the response of lambda function and use 'Event' to invoke lambda function asynchronously.


1 Answers

I am afraid it is not possible. You should design your own technique how to store required information in lamdas. Your option 2 is suitable here. You may look how does it Google: https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h

Below is very raw approach (https://ideone.com/OFCgAq)

#include <iostream>
#include <stack>
#include <functional>

std::stack<std::function<void(void)>> someJobQueue;

template <typename T>
void submitJobToPool(std::string from_here, T callable) {
    someJobQueue.push(std::bind([callable](std::string from_here) { callable(); }, from_here));
}

void runJobFromPool() {
    auto job = someJobQueue.top();
    someJobQueue.pop();
    job();
}

int main() {
    submitJobToPool(__func__, [](){ std::cout << "It's me." << std::endl; });
    runJobFromPool();
    return 0;
}

Unfortunately you will not see a perfect call stack. But you can see from_here in a debugger.

void lambda_1a7009ccf8810b62b59083b4c1779e56() 0x345678920
void lambda_a7009ccf8810b62b59083b4c1779e569() 0x345678910  <-- Here `from_here` will be available: "main"
void runJobFromPool()                          0x234567890
int main(int, char**)                          0x123456780
like image 89
273K Avatar answered Oct 06 '22 21:10

273K