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

Cod*_*ith 2 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(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...
}
Run Code Online (Sandbox Code Playgroud)

我使用此函数创建2个线程并分离它们

鉴于上述实现,我希望可以看到使用-i ssh选项提供的密钥登录到"用户"帐户的2个gnome终端.该脚本应该已经执行并等待提供root密码,同时两个执行线程在pclose()停止时等待各自的gnome-terminal返回.

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

popen()和pclose()的Solaris手册页声称它们都是线程安全的.我试过多种形式的锁定只是为了安全无济于事.

唯一有效的锁定形式是

pthread_lock(&lock1);
popenReturn = popen(buffer,"w");
pclose(popenReturn);    
pthread_unlock(&lock1);
Run Code Online (Sandbox Code Playgroud)

但这给我留下了一个单线程解决方案.

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

否则,我在实施中没有做正确的事情吗?

注意:我最初使用system()而不是popen()和pclose(),但这不是线程安全调用,系统()的Solaris手册页推荐popen()和pclose()

Joh*_*ger 5

gnome-terminal对于你的例子,这个命令可能是一个糟糕的选择,我当然希望它只是一个例子.我不清楚为什么你不直接popen()执行ssh命令.更多关于gnome-terminal以后.

你写

鉴于上述实现,我希望可以看到使用-i ssh选项提供的密钥登录到"用户"帐户的2个gnome终端.该脚本应该已经执行并等待提供root密码,同时两个执行线程在pclose()停止时等待各自的gnome-terminal返回.

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

现在我发现popen()一个提供GUI的程序非常值得怀疑,即使它很简单gnome-terminal,但我倾向于认为这gnome-terminal是特别棘手的事实,因为

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

(gnome-terminal手册页)

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

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