Android,CMDTool,stdout重定向,"致命信号11(SIGSEGV)"

时间:2015-02-17 08:49:01

标签: android c++ linux android-ndk android-source

用例

Android C ++命令行工具lunching" / system / bin / getprop"并将它的标准输出重定向到套接字

问题

Lunching' getprop'以" F / libc(20694)失败:致命信号11(SIGSEGV),代码1,故障地址0x0,在tid 20694(getprop)",代码& logcat片段跟随。

为什么我会收到SIGSEGV?为什么分叉过程会失败?

实施

HRESULT ServiceCore::CreateProcessAndRedirectStdout(IN char* pCmd, IN char** args, OUT SOCKET& stdoutstream) {
    HRESULT hr      = S_OK;
    int     fds[2]  = { 0 };
    pid_t   pid     = 0;
    stdoutstream = 0;
    if (SOCKET_ERROR == socketpair(PF_UNIX, SOCK_STREAM, 0, fds))
        goto ErrExit;
    stdoutstream = fds[1];
    if((pid = fork()) < 0)
        goto ErrExit;
    if (pid == 0) {
        // The newly created process
        __android_log_print(ANDROID_LOG_INFO, "ServiceCore", "CreateProcessAndRedirectStdout>> '%s' started", pCmd);
        int newfd = dup2(fds[0], STDOUT_FILENO);
        __android_log_print(ANDROID_LOG_INFO, "ServiceCore", "CreateProcessAndRedirectStdout>> '%s' newfd:%d, oldfd:%d", pCmd, newfd, fds[0]);
        _ASSERT(newfd == STDOUT_FILENO);

        close(fds[0]);
        close(fds[1]);
        execvp(pCmd, args);
        __android_log_print(ANDROID_LOG_INFO, "ServiceCore", "CreateProcessAndRedirectStdout>> '%s' FAILED", pCmd);
        exit(1);
    }
    __android_log_print(ANDROID_LOG_INFO, "ServiceCore", "CreateProcessAndRedirectStdout>> '%s(%d)' Created", pCmd, pid);
    return S_OK;
ErrExit:
    if (0 != pid)
        kill(pid, SIGTERM);
    close(fds[0]);
    close(fds[1]);
    stdoutstream = 0;
    return hr;
}

...
        char* args[] = { 0 };
        SOCKET soc;
        if (SUCCEEDED(hr = CreateProcessAndRedirectStdout("/system/bin/getprop", args, soc))) {
            errno = 0;
            __android_log_print(ANDROID_LOG_INFO, "ServiceCore", "SendConfig>> Reading props");
            char pTmp[256000];
            int iRet = read(soc, pTmp, sizeof(pTmp));// Read the first few lines
        }

...

logcat的

I/ServiceCore(20689): CreateProcessAndRedirectStdout>> '/system/bin/getprop(20694)' Created

I/ServiceCore(20689): SendConfig>> Reading props

I/ServiceCore(20694): CreateProcessAndRedirectStdout>> '/system/bin/getprop' started

I/ServiceCore(20694): CreateProcessAndRedirectStdout>> '/system/bin/getprop' newfd:1, oldfd:10

F/libc    (20694): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 20694 (getprop)

1 个答案:

答案 0 :(得分:1)

您滥用execvp()的方式是getprop未编写处理。引用execvp()的OSX / BSD(但实际上是通用的)手册页

  

execv(),execvp()和execvP()函数提供一个指向以null结尾的字符串的指针数组,这些字符串表示可用的参数列表        到新计划。按惯例,第一个论点应指向        与正在执行的文件关联的文件名。数组        指针必须由NULL指针终止。

你破坏了这个约定,通过传递一个NULL元素的数组,当你应该将程序的名称作为第一个元素传递,然后是一个终止的NULL元素。

这会将getprop设置为失败,因为它会考虑只有一个参数(本身)的可能性,在这种情况下它会显示所有内容。

    if (argc == 1) {
        list_properties();

但是如果它没有1个参数,它假设它必须有两个或更多,并尝试取消引用第二个,应该是名称你要获得的财产。

    property_get(argv[1], value, default_value);

将一个无效且可能为空的指针代替属性名称传递给property_get()最终会在bionic libc内部失败,可能是__system_property_find()的实现调用了strlen()。

如果您按照fadden的建议检查了堆栈跟踪,您可能会在libc中看到一个地址,可能是strlen()。