pclose() 在多线程环境中过早返回 (Solaris 11) [英] pclose() prematurely returning in a multi-threaded environment (Solaris 11)

查看:82
本文介绍了pclose() 在多线程环境中过早返回 (Solaris 11)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

这是一个非常简单的实现:

void* SshConnection(void* args){字符缓冲区[5000];文件* popenReturn = NULL;//获取要连接的主机名const char* 主机名 = (const char*)args;snprintf(缓冲区,大小(缓冲区),"/usr/bin/gnome-terminal -x bash -c \""ssh -t 用户@%s"-i/home/user/.ssh/key.key""\\\"/home/user/DoRootThings.bash\\" ",主机名);popenReturn = popen(buffer,"w");pclose(popenReturn);//...稍后再次连接到主机并查看 DoRootThings.bash 的结果...}

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

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

相反,有 2 个 gnome-terminal 打开,它们正在等待 root 密码.1 个线程的执行在 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 命令对于您的示例来说可能是一个糟糕的选择,我当然希望它只是 一个例子.我不清楚你为什么不直接 popen() 执行 ssh 命令.稍后会详细介绍 gnome-terminal.

你写

<块引用>

鉴于上述实现,我希望有 2 个 gnome-terminals使用他们的密钥登录到用户"帐户的可见提供了 -i ssh 选项.脚本应该已经执行了并且正在等待在两个线程时提供 root 密码的执行已在 pclose() 处停止,同时等待它们要返回的相应 gnome 终端.

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

现在我发现 popen() 一个呈现 GUI 的程序非常值得怀疑,即使是像 gnome-terminal 一样简单的程序,但我倾向于猜测 gnome-terminal 特别棘手,因为

<块引用>

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

(gnome-terminal 手册页)

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

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

I'm trying to implement a tool that starts 2 ssh connections and executes a script that requires root permission.

Here is a very simple implementation:

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...
}

I create 2 threads using this function and detach them

Given the above implementation I would expect 2 gnome-terminals to be visible that have logged into the 'user' account using they keys provided with the -i ssh option. The script should have been executed and is waiting for the root password to be provided while both threads of execution have stopped at pclose() while waiting for their respective gnome-terminals to return.

Instead, 2 gnome-terminals do open and they are waiting for the root password. The execution for 1 of the threads stops at the pclose() while the other threads pclose() immediately returns. This thread then continues onto look at the results of DoRootThings.bash without there being any results since it is still waiting for the password to execute!

Solaris man page for popen() and pclose() claims that they are both thread safe. I have tried multiple forms of locking just to be safe to no avail.

The only form of locking that works is

pthread_lock(&lock1);
popenReturn = popen(buffer,"w");
pclose(popenReturn);    
pthread_unlock(&lock1);

but this leaves me with a single threaded solution.

Is this a case of the man page being wrong and popen() and pclose() are not thread safe? If so, is there a locking solution that will fix this?

otherwise, am I not doing something correct in my implementation?

NOTE: I initially used system() instead of popen() and pclose() but this is not a thread safe call and the Solaris man page for system() reccomends popen() and pclose()

解决方案

The gnome-terminal command is probably a poor choice for your example, and I certainly hope it's just an example. It's unclear to me why you're not popen()ing the ssh command directly. More on gnome-terminal later.

You write

Given the above implementation I would expect 2 gnome-terminals to be visible that have logged into the 'user' account using they keys provided with the -i ssh option. The script should have been executed and is waiting for the root password to be provided while both threads of execution have stopped at pclose() while waiting for their respective gnome-terminals to return.

, but that's not what I would expect. Calling pclose() should first-off close the stream, which the process on the other end will see as EOF on its standard input. The function will then wait for the child process terminate, but that process should not block on any attempts to read from its standard input. I would normally expect both pclose() calls to return quickly.

Now I find it highly questionable to popen() a program that presents a GUI, even as simple of one as gnome-terminal's, but I'm inclined to guess that gnome-terminal is especially tricky on account of the fact that

By default, all GNOME terminals share a single process, reducing memory usage. This can be disabled by starting gnome-terminal with the --disable-factory option.

(gnome-terminal manual page)

I'm sure you can appreciate that that single-process behavior is likely to play havoc with an API that expects to create and manage separate child processes. I suspect that this is the reason for the observed difference in the behavior of the two calls.

Furthermore, you should check the return values of your function calls, which your example does not demonstrate. I'm not certain that your popen() and / or pclose() should be signaling errors, but I'd rate it a good possibility.

这篇关于pclose() 在多线程环境中过早返回 (Solaris 11)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆