pclose() prematurely returning in a multi-threaded environment (Solaris 11)

牧云@^-^@ 提交于 2021-01-28 04:39:45

问题


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()


回答1:


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.



来源:https://stackoverflow.com/questions/48159534/pclose-prematurely-returning-in-a-multi-threaded-environment-solaris-11

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!