//===============================
string& Pipe::exec_filter(const string& path, string& iobuf)
{
pid_t pid;
int nb, status;
fd_set read_fds;
// check access mode
if(::access(path.c_str(), X_OK) == -1)
throw general_exception("Pipe::exec_filter:" + string(strerror(errno)));
if(::pipe(fds1_) < 0 || ::pipe(fds2_) < 0 || (pid = ::fork()) < 0)
throw general_exception("Pipe::exec_filter:" + string(strerror(errno)));
else if(pid > 0) { // Parent
close(fds1_[0]);
close(fds2_[1]);
// write
write(fds1_[1], iobuf.c_str(), iobuf.length());
close(fds1_[1]);
// wait for something to read
FD_ZERO(&read_fds);
FD_SET(fds2_[0], &read_fds);
int e = select(fds2_[0] + 1, &read_fds, NULL, NULL, &read_timeout_);
if(e == -1) throw general_exception("Pipe::exec_filter: parent: " + string(strerror(errno)));
else if(!e) throw general_exception("Pipe::exec_filter: parent: " + string(strerror(errno=ETIMEDOUT)) + " [" + path + "]");
// read
char buffer[256+1];
iobuf = "";
while((nb = read(fds2_[0], buffer, 256)) > 0) {
*(buffer+nb) = '\0';
iobuf += buffer;
}
// Wait for child exit
if((e = wait(&status)) == -1)
throw general_exception("Pipe::exec_filter: parent: " + string(strerror(errno)));
// process any child errors
if(status)
throw general_exception("Pipe::exec_filter: child: " + string(strerror(status)) + " [" + path + "]");
}
else { // Child
// dup stdin/stdout
close(fds1_[1]);
close(fds2_[0]);
if(fds1_[0] != STDIN_FILENO && dup2(fds1_[0], STDIN_FILENO) != STDIN_FILENO)
_exit(errno);
if(fds2_[1] != STDOUT_FILENO && dup2(fds2_[1], STDOUT_FILENO) != STDOUT_FILENO)
_exit(errno);
// set nice
errno = 0;
if(nice_inc_ && ::nice(nice_inc_) == -1 && errno)
_exit(errno);
::execv(path.c_str(), NULL);
_exit(1);
}
return iobuf;
}
//===============================
IPC problems on NetBSD
Hi
I am working on a linux/unix filter that uses plugins to extract info from web pages. I have sucessfully compiled and run the program on the following systems:
x86 Fedora Linux FC2 running Linux 2.6 kernel
x86 Debian GNU/Linux 3.0 running Linux 2.4 kernel
AMD64 Fedora Core release 3 running Linux 2.6 kernel
The problem is when I try to run it on x86 NetBSD 1.6.1
It compiles, but when I try to run the program the child process (running the plugin) spits out an error:
Unknown error [256]
Here is the IPC between the parent/child:
Anyone have an idea why this child breaks on NetBSD?
I know the plugin returns 0, still it seems like the status from the wait call
equals 256.
Is the bahavior of wait function different on BSD?
There are two problems that I can see. Firstly, the value that wait(2) stores in status is an opaque status value, not the exit value of the child. To get at the exit status of the child, you need to use the WIFEXITED/WEXITSTATUS/etc. macros. Secondly, you need to pass a valid argv array to execv so that, at least, argv[0] is the name of the program and argv[1] is NULL. It might be easier to use execl instead and just pass path.c_str() twice, e.g. execl(path.c_str(), path.c_str(), NULL);
Quote:
There are two problems that I can see. Firstly, the value that wait(2) stores in status is an opaque status value, not the exit value of the child. To get at the exit status of the child, you need to use the WIFEXITED/WEXITSTATUS/etc. macros.
I noticed this mistake too. Now that Im back on linux Ill fix that and see if it helps.
Quote:
Secondly, you need to pass a valid argv array to execv so that, at least, argv[0] is the name of the program and argv[1] is NULL. It might be easier to use execl instead and just pass path.c_str() twice, e.g. execl(path.c_str(), path.c_str(), NULL);
I think that is what I am doing. The 'path' string is the full path of the plugin. Nothing more, nothing less.
If the above doesnt help Ill try the execl.
Thanks
Whow I feel stupid hehe
I changed
-if(status)
+if(WEXITSTATUS(status))
That gave me a Operation not permitted error from the child.
Then I changed
-::execv(path.c_str(), NULL);
- _exit(1);
+ ::execl(path.c_str(), path.c_str());
+ _exit(errno);
That gave me a Bad address error
Changed
-::execl(path.c_str(), path.c_str());
+::execl(path.c_str(), path.c_str(), NULL); // This is where I started feeling stupid...
and now it works =D
Thanks a lot!
I changed
-if(status)
+if(WEXITSTATUS(status))
That gave me a Operation not permitted error from the child.
Then I changed
-::execv(path.c_str(), NULL);
- _exit(1);
+ ::execl(path.c_str(), path.c_str());
+ _exit(errno);
That gave me a Bad address error
Changed
-::execl(path.c_str(), path.c_str());
+::execl(path.c_str(), path.c_str(), NULL); // This is where I started feeling stupid...
and now it works =D
Thanks a lot!
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement