pclose()在多线程环境中过早返回(Solaris 11)

pclose()在多线程环境中过早返回(Solaris 11),c,multithreading,solaris,popen,C,Multithreading,Solaris,Popen,我正在尝试实现一个工具,它启动2个ssh连接并执行一个需要root权限的脚本 下面是一个非常简单的实现: void* SshConnection(void* args) { char buffer[5000]; FILE* popenReturn = NULL; //get the hostname to connect to const char* hostname = (const char*)args; snprintf(buffer, sizeof(bu

我正在尝试实现一个工具,它启动2个ssh连接并执行一个需要root权限的脚本

下面是一个非常简单的实现:

void* SshConnection(void* args)
{
   char buffer[5000];
   FILE* popenReturn = NULL;

   //get the hostname to connect to
   const char* hostname = (const char*)args;

   snprintf(buffer, sizeof(buffer),
           "/usr/bin/gnome-terminal -x bash -c \""
           "ssh -t user@%s "
           "-i /home/user/.ssh/key.key "
           "\\\"/home/user/DoRootThings.bash\\\" ",hostname);

   popenReturn = popen(buffer,"w");
   pclose(popenReturn);

   //...connect to the host again later on and look at results of DoRootThings.bash...
}
我使用这个函数创建了两个线程并分离它们

考虑到上面的实现,我希望可以看到2个gnome终端,它们使用-I ssh选项提供的密钥登录到“用户”帐户。脚本应该已经执行,并且正在等待提供根密码,而执行的两个线程都已在pclose()处停止,同时等待各自的gnome终端返回

相反,2个gnome终端确实打开了,它们正在等待根密码。其中一个线程的执行在pclose()处停止,而其他线程pclose()立即返回。然后,该线程继续查看DoRootThings.bash的结果,没有任何结果,因为它仍在等待密码执行

用于popen()和pclose()的Solaris手册页声称它们都是线程安全的。为了安全起见,我尝试了多种形式的锁定,但都无济于事

唯一有效的锁定形式是

pthread_lock(&lock1);
popenReturn = popen(buffer,"w");
pclose(popenReturn);    
pthread_unlock(&lock1);
但这给我留下了一个单线程解决方案

这是一个手册页错误的情况,并且popen()和pclose()不是线程安全的吗?如果是这样,是否有一种锁定解决方案可以解决此问题

否则,我在实现中是否做了一些不正确的事情


注意:我最初使用system()而不是popen()和pclose(),但这不是一个线程安全调用,system()的Solaris手册页会返回popen()和pclose()

对于您的示例来说,
gnome terminal
命令可能是一个糟糕的选择,我当然希望这只是一个示例。我不清楚为什么不直接使用
ssh
命令。有关gnome终端的详细信息,请稍后参阅

你写

考虑到上述实现,我预计将使用2个gnome终端 可见已使用密钥登录到“用户”帐户的用户 提供了-i ssh选项。脚本应该已经执行了 并且正在等待提供根密码,而这两个线程 的执行已在pclose()处停止,同时等待 返回相应的gnome终端

,但这不是我所期望的。调用
pclose()
应该首先关闭流,另一端的进程在其标准输入中将其视为EOF。然后,函数将等待子进程终止,但该进程不应阻止从其标准输入读取的任何尝试。我通常希望两个
pclose()
调用都能快速返回

现在,我发现
popen()

默认情况下,所有GNOME终端共享一个进程,从而减少内存使用。这可以通过使用
--disable factory
选项启动gnome终端来禁用

()

我相信您可以理解,单进程行为可能会对期望创建和管理独立子进程的API造成严重破坏。我怀疑这就是观察到的两个调用行为差异的原因


此外,您应该检查函数调用的返回值,您的示例没有演示这些返回值。我不确定您的
popen()
和/或
pclose()
是否应该发出错误信号,但我认为这很有可能。

pclose
将等待子进程正常退出;这是法律所要求的。我认为gnome终端工厂在资金上是正确的(非常好的捕获!)。第二个
popen
将生成一个进程,该进程在将其工作负载移交给第一个进程后会很快退出。如果gnome终端已经在运行,那么我希望两个
pclose
调用都能快速返回。也许OP可以确认。将--disable factory选项添加到gnome终端已经修复了立即返回的popen()调用!打开gnome终端可以很容易地获得一个单独的界面,为脚本提供密码并查看脚本输出。直接弹出ssh命令肯定是一个有效的解决方案,但需要更多的返工。popen()和pclose()未返回任何错误