这个问题或多或少与embedded perl in C, perlapio - interoperability with STDIO有关,我认为我已经为Windows环境解决了这个问题。如果这个新问题也得到解决,我会发布一个完整的解决方案。
在链接的问题中,
StoryTeller gave me the hint
使用PerlIO_findFILE()
来解决当前的问题,但Linux上的相同代码表现得很奇怪。
Perl的dup2()
似乎在Win32上有不同的行为,其中dup2()
是win32_dup2()
的宏,据我所知只是使用{{1}来自dup2()
。
在Win32上,Perl的版本在成功时返回零,在出错时返回非零,但在Linux上将使用默认的ANSI io.h
,而不是返回新的文件描述符。然后,如果一切顺利,我将不得不检查dup2()
。
如果拨打errno
,则PerlIO_findFILE()
设置为"非法搜索" (错误29 - errno
),然后ESPIPE
,dup
,dup2
等pipe
仍设置为"非法搜索" ,errno
上的任何进一步检查仍然会看到相同的错误。
(在实践中,一切都对我有用,因为没有实际错误。此外,通过检查errno
的解决方案不是线程安全的,因为在系统调用和检查之间另一个步骤可能会重置错误。)
请注意,我有
errno
实际上我使用Perl5.14.1。
我在这里做错了吗?
这是一个简化的代码段:
#define PERLIO_NOT_STDIO 0
答案 0 :(得分:3)
errno
没有意义,因此不能用于确定是否发生错误。值得注意的是,这些调用不需要(通常也不会)成功重置errno
。在通话之前清除errno
甚至都不安全,因为即使没有发生错误,呼叫也可能设置errno
。
据我所知,Perl dup2
的{{1}}返回与POSIX相同的值(错误时为-1
,成功时为newfd
)。
#ifndef HAS_DUP2
int
dup2(int oldfd, int newfd)
{
#if defined(HAS_FCNTL) && defined(F_DUPFD)
if (oldfd == newfd)
return oldfd;
PerlLIO_close(newfd);
return fcntl(oldfd, F_DUPFD, newfd);
#else
#define DUP2_MAX_FDS 256
int fdtmp[DUP2_MAX_FDS];
I32 fdx = 0;
int fd;
if (oldfd == newfd)
return oldfd;
PerlLIO_close(newfd);
/* good enough for low fd's... */
while ((fd = PerlLIO_dup(oldfd)) != newfd && fd >= 0) {
if (fdx >= DUP2_MAX_FDS) {
PerlLIO_close(fd);
fd = -1;
break;
}
fdtmp[fdx++] = fd;
}
while (fdx > 0)
PerlLIO_close(fdtmp[--fdx]);
return fd;
#endif
}
#endif
(来自5.24.1)
这意味着我们可以以独立于平台的方式检测错误,尽管您声称相反。因此,正确的用法是
if ( dup2(fdPipeStdOut[1], fdStdOutOriginal) >= 0 ) {
//do some funny stuff
} else {
//report error
}