AWS Lambda 函数中来自 spawn child_process 的 SIGSEGV

SIGSEGV from spawn child_process in AWS Lambda function

我正在尝试在 AWS Lambda 函数中生成一个同步子进程(到 运行 ffprobe),但它几乎立即(200 毫秒)终止并发出 SIGSEGV 信号。

我对分段错误的理解是,它是一个试图访问它不允许访问的内存的进程。我尝试将内存增加到 1024MB(我使用 128MB,因为每次执行只使用大约 56MB),但这并没有改变任何东西。

我知道我不是唯一遇到此问题的人:https://forums.aws.amazon.com/thread.jspa?threadID=229397

有人知道如何解决这个问题吗?

更新 25/4/2016

为清楚起见,我 运行ning 的代码是:

import { spawnSync } from 'child_process';

exports.handler = (event, context) => {
  process.env.PATH = `${process.env.PATH}:${process.env.LAMBDA_TASK_ROOT}`;
  const ffprobe = './ffprobe';

  const bucket = event.Records[0].s3.bucket.name;
  const key = event.Records[0].s3.object.key;
  console.log(`bucket: ${bucket}`);
  console.log(`key: ${key}`);

  const url = 'http://my-clip-url.com'; // An s3 presigned url.
    if (!url) {
      throw new Error('Clip does not exist.');
    }

    const command = `-show_format -show_streams -print_format json ${url}`;

    try {
      const child = spawnSync(ffprobe, command.split(' '));
      console.log(`stdout: ${child.stdout.toString()}`)
      console.log(`stderr: ${child.stderr.toString()}`)
      console.log(`status: ${child.status.toString()}`)
      console.log(`signal: ${child.signal.toString()}`)
    } catch (exception) {
      console.log(`Process crashed! Error: ${exception}`);
    }
};

其输出为:

START RequestId: 6d72847 Version: $LATEST

2016-04-25T19:32:26.154Z    6d72847 stdout: 
2016-04-25T19:32:26.155Z    6d72847 stderr: 
2016-04-25T19:32:26.155Z    6d72847 status: 0
2016-04-25T19:32:26.155Z    6d72847 signal: SIGSEGV
END RequestId: 6d72847
REPORT RequestId: 6d72847   Duration: 4151.10 ms    Billed Duration: 4200 ms    Memory Size: 256 MB Max Memory Used: 84 MB  

我正在使用无服务器框架来 babelify 和部署我的代码。

注意:我已经在 EC2 (http://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html) 上的 ami-bff32ccc 实例上尝试 运行ning 这个二进制文件并且它有效。所以这一定是我正在做的事情(我如何执行 ffprobe)。

前言:

我想知道我是否应该 post 以下内容作为评论或回答。我想知道的原因是因为我对您实际要问的内容有些困惑。初读时,很明显您想克服错误,但您并没有通过向我们展示您的代码等方式帮助我们将其置于上下文中。此外,您 post 编辑的主题中讨论的问题是相关的,但作者提出了一个更笼统的问题:“如何调试问题”,我有一个对此的回答:

回答:

Lambda 日志在 CloudWatch 中可用。 SIGSEGV 是在您尝试访问您不允许的内容(正如您所指出的)时引起的,这可能是因为内存被另一个进程锁定,有时是因为您没有权限访问您正在访问的内容,或者可以访问某些内容,以便将某些内容设置为 nil,稍后用作内存地址等。您可以将日志语句添加到您的代码中,以调查您的函数中实际发生的事情,并使用 CloudWatch 阅读此类日志:http://docs.aws.amazon.com/lambda/latest/dg/monitoring-functions-logs.html

结论

你的问题无法解决,因为你没有完全解释问题,但至少,我向你指出了如何调查它:

  1. 将调试日志添加到您的代码
  2. 使用 CloudWatch 跟踪日志

如果您需要更多帮助,可以post您的代码。

试试这个。让您的 Lambda 函数产生一个 bash shell 来执行此操作:

ulimit -c unlimited cd /tmp $LAMBDA_TASK_ROOT/ffprobe ...

然后检查名为“/tmp/core”的文件,如果存在,将其复制到 S3 存储桶(或其他任何存储桶),并使用 gdb 在您的开发系统或 EC2 主机上对其进行分析。我自己还没有验证过这一点,但我知道默认情况下 ulimit 将为零,核心文件将转储到当前目录。请注意,这些详细信息如有更改,恕不另行通知(如果没记错的话,最近已更改。)

当然,"cd" 可能发生在 lambda 函数中。如果 nodejs 提供了一种设置 ulimit 的方法,它也可以在那里发生。

[编辑:正确的模式是 /tmp/core.%e.%p,参见 "man core" 解释。]

我使用的 ffprobe 版本是从 John Van Sickle's site 获得的,当我 运行 它在 Amazon Linux EC2 实例上工作时它可以工作,但它不能在 AWS Lambda 上工作.

听从 Jeff Learman 的建议,我使用 this wonderful script on the current version of the environment used by AWS Lambda as described here 构建了自己的版本。然后我用我的 Lambda 函数部署了它,它第一次成功了! :)