【问题标题】:SIGSEGV from spawn child_process in AWS Lambda function来自 AWS Lambda 函数中的 spawn child_process 的 SIGSEGV
【发布时间】:2016-08-13 11:55:42
【问题描述】:

我正在尝试在 AWS Lambda 函数中生成一个同步子进程(以运行 ffprobe),但它几乎立即(200 毫秒)因信号 SIGSEGV 而死。

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

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

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

2016 年 4 月 25 日更新

为了清楚起见,我正在运行的代码是:

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 实例上运行此二进制文件,它可以工作。所以这一定是我正在做的事情(我是如何执行 ffprobe 的)。

【问题讨论】:

  • 您是否将 ffmpeg 和 ffprobe 上传到您的 AWS lambda?
  • 是的,它就在那里。我正在使用无服务器框架并设置了“includePaths”属性以包含 ffprobe 文件。

标签: node.js amazon-web-services child-process aws-lambda ffprobe


【解决方案1】:

试试这个。让您的 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”来解释。]

【讨论】:

  • 感谢您的回复,杰夫。我试过了,但/tmp 中的唯一文件是-rw------- 1 sbx_user1052 494 9134080 Apr 28 21:58 core.ffprobe-static.12。那个文件是什么?那能有什么用吗?为了清楚起见,我运行的命令是'ulimit -c unlimited; cd /tmp; $LAMBDA_TASK_ROOT/ffprobe -version;
  • 这看起来像一个核心文件,虽然不是我所期望的。试试看,让我们知道!
  • 模式是/tmp/core.%e.%p(参见“man core”来解释)。
  • 嘿杰夫。我尝试了我在 Lambda 运行的同一个盒子上获得的核心文件之一,我得到的只是:gist.github.com/patoncrispy/24b203acd6563216883bf5379f50eab6。我认为缺少输出意味着我正在使用的 ffprobe 的静态构建没有启用调试...?
  • 是的,就是这个意思。 :-( 也许您可以从源代码构建或从 ffprobe 用户那里获得帮助。
【解决方案2】:

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

按照 Jeff Learman 的建议,我在 AWS Lambda as described here 使用的当前环境版本上使用 this wonderful script 构建了自己的版本。然后我用我的 Lambda 函数部署它,它第一次工作! :)

【讨论】:

    【解决方案3】:

    序言:

    我想知道是否应该将以下内容作为评论或答案发布。我之所以想知道,是因为我对您实际要问的内容有些困惑。初读时,很明显您想要克服错误,但您并没有帮助我们将其上下文化,例如,向我们展示您的代码。此外,您发布的帖子中讨论的问题是相关的,但作者提出了一个更普遍的问题:“如何调试问题”,我对此有一个答案:

    回答:

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

    结论:

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

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

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

    【讨论】:

    • 感谢您的帮助!我已经用示例代码和输出日志更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 2015-01-06
    • 1970-01-01
    • 2012-07-27
    • 1970-01-01
    • 2019-08-28
    • 1970-01-01
    • 2019-01-21
    • 2016-02-29
    相关资源
    最近更新 更多