1

I'm using the getcwd function to retrieve the current working directory of my application. In some cases it fails and errno is ENOENT. I call getcwd from different threads, but serially and sometimes I face with ENOENT, but I don't know why. The link above says that ENOENT means that "The current working directory has been unlinked." but the directory exists.

Here is a snippet of the function I use:

UPDATE: Code updated with advice from @Aganju and @molbdnilo:

std::string get_working_dir()
{
    char buf[PATH_MAX];
    memset(buf, 0, sizeof(buf));
    char * result = getcwd(buf, sizeof(buf));
    std::string working_path = buf;
    // Check for possible errors.
    if (result == NULL)
    {        
        switch (errno)
        {
            case EACCES:
                break;
            case EFAULT:
                break;
            case EINVAL:
                break;
            case ENAMETOOLONG:
                break;
            case ENOENT:
            {
                if (working_path.empty())
                {
                    const char* pwd = getenv("PWD");
                    working_path = (pwd) ? pwd : "";
                }
                break;
            }
            case ERANGE:
                break;
            default:
                break;
        }
        return working_path;
    }
}

In case I face ENOENT, I retrieve the "PWD" environment variable because I work on CentOS 5.11 and Ubuntu 16.04, and when getcwd fails on CentOS it returns an empty buffer.

UPDATE:

I have noticed that the call from the main thread does not fail, but when I call the function from another thread it fails and errno is ENOENT.

4

2 回答 2

3

正如molbdnilo所说,您需要先检查返回值。

您链接到的手册指出:

[...] 失败时,这些函数返回 NULL,并设置 errno 以指示错误。[...]

换句话说,如果没有失败,errno没有设置,并且包含之前发生的任何调用中包含的任何内容,可能是很久以前,这在此上下文中是没有意义的。

使用类似的东西char * result = getcwd(buf, sizeof(buf));,然后检查if (result == NULL) { switch (errno) ...等。

于 2017-08-24T14:46:08.340 回答
1

这可能发生在以下情况,我们可以用一个多进程序列图来说明,使用 shell 脚本语法:

process A                     process B
$ cd ~                        $ cd ~
user $ mkdir foo            
user $ cd foo
                              user $ rm -rf foo              
user/foo $ pwd
/home/user/foo
user/foo $ cd .
cd: error retrieving current
directory: getcwd: cannot access
parent directories: No such file or directory

类 Unix 操作系统中的每个进程都有一个当前工作目录,其中包含对文件系统中对象的引用。在进程删除当前目录之前,该对象不能作为可用空间回收。

上面,进程 A 继续保留以前的目录 ~/foo。该路径不再存在于目录结构中,但目录对象继续存在。

系统调用实现了这getcwd一点:它看到调用进程的当前工作目录没有链接到目录结构中,因此没有路径,所以它报告错误。

shell 命令之所以pwd有效,是因为它只是重复了一段 shell 无需调用就知道的数据getcwd;但是当我们尝试时cd .,会发生错误(在 GNU/Linux 系统上使用 Bash 复制;结果可能会有所不同)。

于 2017-08-24T15:56:42.897 回答