【问题标题】:Calling exec returns errno 14 (bad address) with absolute path调用 exec 以绝对路径返回 errno 14(错误地址)
【发布时间】:2012-04-08 22:34:09
【问题描述】:

为一门课程制作一个简单的 cgi 服务器。为此,在某些时候我必须创建一个 fork/exec 来启动 cgi 处理程序,问题是 exec 不断返回 errno 14。我在独立版本中尝试了以下代码,它可以使用和不使用绝对小路。

代码如下:

static void _process_cgi(int fd, http_context_t* ctx)
{
    pid_t childProcess;
    int ret;
    char returnValue[1024];
    log(LOG, "calling cgi", &ctx->uri[1], 0);

    if((childProcess = fork()) != 0)
    {
        ///
        /// Set the CGI standard output to the socket.
        ///
        dup2(fd, STANDARD_OUTPUT);
            //ctx->uri = "/simple.cgi"

        execl("/home/dvd/nwebdir/simple.cgi",&ctx->uri[1]);
        sprintf(returnValue,"%d",errno);

        log(LOG, "exec returned ", returnValue, 0);
        return -1;
    }

    ret = waitpid(childProcess,NULL,0);
    sprintf(returnValue,"%d",ret);
    log(LOG, "cgi returned", returnValue, 0);
}

这是服务器在到达我的代码之前通过的系统调用列表(按顺序): -chdir - 叉 -setpqrp - 叉 我不知道这是否相关,但在我的测试程序中我没有 chdir 也没有 setpqrp。

测试代码如下:

pid_t pid;

    if ((pid = fork()) != 0)
    {
        execl("simple.cgi","simple");
        //execl("/home/dvd/nwebdir/simple.cgi","simple");
        return 0;
    }
    printf("waiting\n");
    waitpid(pid, NULL, 0);
    printf("Parent exiting\n");

注意我已经在服务器代码中尝试了 execl 和 execlp。

您可以在这里找到基本的服务器实现(没有 CGI),我所做的唯一更改是在 web 功能中: http://www.ibm.com/developerworks/systems/library/es-nweb/index.html

问候

【问题讨论】:

    标签: unix cgi exec fork


    【解决方案1】:

    顺便说一句,您复制的代码不正确,或者它有逻辑错误。 Fork() 向父进程返回非零值,而不是子进程,因此应恢复条件。 (这里没有评论按钮,所以做出回答。)

    【讨论】:

      【解决方案2】:
          execl("/home/dvd/nwebdir/simple.cgi", &ctx->uri[1], (char *)0);
      

      execl() 的最后一个参数必须为空 char *。你通常可以写NULL而不是(char *)0,但如果你有#define NULL 0并且你在sizeof(int) != sizeof(char *)的机器上,比如64位系统,它可能不会产生正确的结果。

      【讨论】:

      • 需要显式强制转换的原因是编译器通常可以从函数原型中推断出要放入堆栈的参数的长度。然而,在这种情况下,最后一个指针是变量参数列表的一部分(原型中的...),因此编译器在看到0 时只会推送intexecv() 函数不会出现此问题,因为它传递了一个数组 char * const argv[]
      【解决方案3】:
      execl("simple.cgi","simple", NULL);
      

      null 是必需的,因为 execl() 是一个可变参数 - 函数。

      【讨论】:

      • 成功了,但为什么它在测试版本中有效,而不是在服务器版本中?
      • 调用未定义的行为会导致未定义的(读取不稳定)行为,包括有时看起来有效。
      猜你喜欢
      • 1970-01-01
      • 2015-08-26
      • 1970-01-01
      • 1970-01-01
      • 2010-09-05
      • 2015-10-16
      • 1970-01-01
      • 2023-03-15
      • 2016-07-23
      相关资源
      最近更新 更多