Reading variables from a forked child (Python C/API)

Jonathan Conrad rahu at gawab.com
Fri Jul 15 14:46:04 EDT 2005


#ifdef def
Donn Cave wrote:
> Quoth MrEntropy <fake at doesntexist.dud>:
> 
> | 	I'm having a little trouble getting an idea running. I am writing a C 
> | program which is really a frontend to a Python program. Now, my C 
> | program starts up, does some initialisation like initialisation of it's 
> | variables and Py_Initialize() and then it fork()s. After forking the 
> | child launches the python program with Py_Main() and with the parent I 
> | want to be able to read the variables of the Python program. I have 
> | tried many ways but cannot find a solution to do this.
> 
> That's because there is no solution.  After a fork, the only effect
> observable in the parent process is the return value of fork, which
> will have a non-zero value.  Subsequent execution in the child process
> occurs completely independently from the parent, and leaves no trace
> whatever.  So you can't read variables from memory, that were set by
> the child.

Though there is probably some solution involving a third party 
such as POSIX threads, Linux has a clone(2) procedure which 
fork(2) is a macro of.  It is tricky to use, but allows for 
having the child process have the same pid, memory, memory 
mappings, file tables, etc.  BSD mmap(2) is more portable and can 
be used for interprocess sharing.  The solution which Don Cave 
provided is probably the one that Mr. Entropy needs to start 
with.  More specifically, ...

#else

int main (int argc, char **argv)
{
	int fd0, fd1, fd2;
	{
		int fd_in [2], fd_out [2], fd_err [2];
		pipe (fd_in);  fd0 = fd_in  [1];
		pipe (fd_out); fd1 = fd_out [0];
		pipe (fd_err); fd2 = fd_err [0];
		if (!fork ()) {
			dup2 (fd_in  [0], 0); close (fd0);
			dup2 (fd_out [1], 1); close (fd1);
			dup2 (fd_err [1], 2); close (fd2);
			execl ("python", "python", 0);
			perror ("execution failed");
			exit (1);
		}
	}

	write (fd0, "print None\n", 11);
	write (1, b, read (fd1, b, sizeof (b) /* 5 or more */));

	#define write0(q...) write (fd0, "print " #q "\n",	\
					sizeof (#q) + 5 + 1 - 1)
	write0 (True);  write (1, b, read (fd1, b, sizeof (b)));
	write0 (5, str (5.0), ...);
	write (1, b, read (fd1, b, sizeof (b)));
	return write0 (True, False, None,
			True and False,
			True and None,
			False and None,
			True and False and None) && 0;
}

#endif



More information about the Python-list mailing list