2

I would like to try the custom C++ runtime for AWS Lambda and testing it locally using SAM. Unfortunately I get the error Runtime exited without providing a reason (compare error details below). How can I run C++ Lambda functions locally with SAM?

Approach:

I am following the exact steps described in official C++ Introduction blog, up to the last step of "Create your C++ function". The rest of the blog is about deploying the function on Lambda (which I DO NOT want to do, since I would like to use SAM locally).

In order to use SAM, I am putting a template.yaml in the build dir. The structure of the build dir now looks like this:

├── CMakeCache.txt
├── CMakeFiles
|   |...
├── cmake_install.cmake
├── hello
├── hello.zip
├── Makefile
└── template.yaml

6 directories, 37 files

This is the content of the template.yaml in the build dir:

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
  cpp hello world

Globals: # default settings across all resources if nothing else is specified
  Function:
    Timeout: 15

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello.zip # relative location or S3 key
      Handler: hello # function to handle call? Why is this hello and not main?
      Runtime: provided
      Events:
        HelloWorld: # the name of the event
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get

Outputs:
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

Invoke:

I am running sam local start-api --debug in the debug folder. I am invoking the function by going to 127.0.0.1:3000/hello in chrome.

Error:

Some details from the message that results from invoking the URL:

...
Invoking hello (provided)
Decompressing /home/path/to/folder/test_cpp_local/aws-lambda-cpp/build/hello_cpp/build/hello.zip

Fetching lambci/lambda:provided Docker container image......
Mounting /tmp/tmpm9djt4mb as /var/task:ro,delegated inside runtime container
/var/task/bin/hello: error while loading shared libraries: /var/task/lib/libc.so.6: file too short
START RequestId: 3435a342-d86d-1a59-df1a-10167070cd22 Version: $LATEST
END RequestId: 3435a342-d86d-1a59-df1a-10167070cd22
REPORT RequestId: 3435a342-d86d-1a59-df1a-10167070cd22  Init Duration: 29.71 ms Duration: 0.00 ms   Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 6 MB   
{
  "errorType": "Runtime.ExitError",
  "errorMessage": "RequestId: 3435a342-d86d-1a59-df1a-10167070cd22 Error: Runtime exited without providing a reason"
}
Function returned an invalid response (must include one of: body, headers, multiValueHeaders or statusCode in the response object
...

My System:

I am building on a Ubuntu 16.04 using cmake 3.5.1, g++ 4.5.0, gcc 4.5.0

Ideas how to solve this:

I somehow have to build remote on a machine that uses AWS Linux (I hope that this is not the case)

I could use the CloudFormationPackage as recommended here stackoverflow. I would like to avoid this, since I would like to test locally only.

User12547645
  • 6,955
  • 3
  • 38
  • 69
  • Are you sure about the `Handler` value? Did you closely follow point 2 from https://aws.amazon.com/blogs/compute/introducing-the-c-lambda-runtime/ If followed this tutorial and the result works, it should behave the same way in your local SAM environment. – adamkonrad Oct 18 '19 at 15:49
  • Also, you can build on AWS Linux in Virtualbox. – adamkonrad Oct 18 '19 at 15:51

2 Answers2

2

Run inside a docker container

I assume that this is an issue with SAM. I was able to this just the way I build it using docker-lambda. For this I had to extract hello.zip and than call it with

docker run --rm -v "<path/to/hello>":/var/task lambci/lambda:provided handler

Using this workaround I did not need to build statically.

Build inside a docker container

You can also build inside an amazonlinux container. A hello_world Dockerfile would look like this (includes the program itself):

FROM amazonlinux:latest

RUN yum -y install make 
RUN yum -y install git 
RUN yum -y install gcc-c++
RUN yum -y install nano 
RUN yum -y install zip 
RUN yum -y install clang 
RUN yum -y install gcc-c++
RUN yum -y install libcurl-devel 
RUN yum -y install cmake3
RUN export CC=gcc && \
    export CXX=g++ && \
    cd ~  && \
    git clone https://github.com/awslabs/aws-lambda-cpp.git && \
    cd aws-lambda-cpp && \
    mkdir build && \
    cd build && \
    cmake3 .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=~/out && \
    make &&\
    make install && \
    mkdir hello-cpp-world && \
    cd hello-cpp-world && \
    echo -e "// main.cpp\n#include <aws/lambda-runtime/runtime.h>\nusing namespace aws::lambda_runtime;\ninvocation_response my_handler(invocation_request const& request)\n{\n   return invocation_response::success(\"Hello, World!\", \"application/json\");\n}\n\nint main()\n{\nrun_handler(my_handler);\n   return 0; \n}" >> main.cpp && \
    echo -e "cmake_minimum_required(VERSION 3.5)\nset(CMAKE_CXX_STANDARD 11)\nproject(hello LANGUAGES CXX)\nfind_package(aws-lambda-runtime REQUIRED)\nadd_executable(hello \"main.cpp\")\ntarget_link_libraries(hello PUBLIC AWS::aws-lambda-runtime)\naws_lambda_package_target(hello NO_LIBC)" >> CMakeLists.txt && \
    mkdir build &&\
    cd build &&\
    cmake3 .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=~/out && \
    make && \
    make aws-lambda-package-hello
RUN cd / && \
    cp /root/aws-lambda-cpp/build/hello-cpp-world/build/hello.zip /artifacts/hello.zip

Important is, that if you are building in an amazonlinux environment, you have to include aws_lambda_package_target(hello NO_LIBC) to your CMakeLists.txt. This is in order to not include the C runtime as a dependency.

In the example I mounted a folder called artifacts inside my container, to which I am copying the resulting zip file.

User12547645
  • 6,955
  • 3
  • 38
  • 69
  • If only the AWS docs were this clear! Thanks for this, running the Zip within Docker was exactly what I needed. Also added `-e DOCKER_LAMBDA_STAY_OPEN=1 -p 9001:9001` to be able to hit `curl http://localhost:9001/2015-03-31/functions/function/invocations --data @payload.json` for interactive testing. Much easier than SAM. – anotherdave Feb 23 '21 at 11:03
1

The problem is likely here: /var/task/bin/hello: error while loading shared libraries: /var/task/lib/libc.so.6: file too short

Your binary does not even invoke.

You should be able to resolve this problem by building the binary on matching version of AWS Linux or by building a static binary.

adamkonrad
  • 6,794
  • 1
  • 34
  • 41
  • 1
    I clarified the answer. I'd try building a static binary since that's simplest. – adamkonrad Oct 18 '19 at 15:58
  • Okay, so I do have to use a machine using `AWS Linux`. This seems to be a bit annoying to me. I go the impression from https://www.youtube.com/watch?v=qdIa9vTlg9Q that this was not necessary :( – User12547645 Oct 18 '19 at 15:59
  • 1
    Or you can building inside a AWS Linux container, but I don't know the details of that approach :) – adamkonrad Oct 18 '19 at 16:03
  • I was thinking about using Cloud9 for building it... might be the simplest. Could you maybe also help me out with the building commands? How would https://aws.amazon.com/blogs/compute/introducing-the-c-lambda-runtime/ change if I would want to bind the libs statically? – User12547645 Oct 18 '19 at 16:06
  • You need to change the CMake configuration: https://stackoverflow.com/questions/24648357/compiling-a-static-executable-with-cmake – adamkonrad Oct 18 '19 at 16:10
  • It did not work. I was not able to build everything statically. I was also building it in a docker container with amazonlinux. I was not able to run that zip file on Ubuntu, though – User12547645 Oct 19 '19 at 14:10
  • You shouldn't combine two systems/build environments like that. – adamkonrad Oct 20 '19 at 15:06