On Fri, 22 Jan 2010, Ciaran McCreesh wrote:

> 2010/1/18 Benjamin R. Haskell <[email protected]>:
> > The problem is that 'distcc -j' with zeroconf fires off a daemon 
> > (See http://lists.samba.org/archive/distcc/2004q4/002774.html for 
> > the justification -- basically: the startup cost for collecting mDNS 
> > information is worth avoiding in a build that calls distcc many 
> > times.)
> 
> Ebuilds aren't allowed to spawn processes that last longer than the 
> ebuild itself. The same applies to anything you sneakily make ebuilds 
> do.

I'm not sure what you mean by "aren't allowed to"...  "are prohibited by 
official policy"?  So, an ebuild calling distcc -j would be 
out-of-bounds?   Or do you mean that the wait is supposed to be enforced 
programmatically?

The 'distcc -j' isn't called in an ebuild -- I use it in my own 
/etc/paludis/bashrc to set up my $MAKEARGS.


> > So, from the way 'outputwrapper' works, the problem is that 
> > 'outputwrapper's fd's aren't in the set that get closed by 'distcc' 
> > before daemonizing.  And 'distcc' would thus sleep for 20 seconds 
> > every time 'bashrc' got sourced, unless I happened to have run 
> > 'distcc' outside of paludis (so that the daemon was already running 
> > outside of outputwrapper).
> 
> Are you really really sure that that's the issue? I strongly suspect 
> that it's not in the least bit FD related, since we've been passing a 
> 'spare' FD around (to avoid having to use sockets, which have 
> permissions ick) for ages.

Not absolutely sure, no... but...

> I suspect the real problem is that the daemon doesn't fork itself
> twice, to make itself owned by init rather than the spawning process.

...the daemon spawned by distcc -j appears to not double-fork, but it 
does setsid().  And, the attached program triggers the same behavior 
w.r.t. outputwrapper, unless called with the with-closed-fds wrapper 
from my initial email.  (double-forked-simple.c just double forks, 
closes fd's 0-2, setsid()s, and sleeps for 20 seconds.)  But maybe I'm 
missing something the 'distcc' code misses, too.

> > I'm going to suggest on the distcc list that the daemonization 
> > process closes a larger set of fd's.  (There is also a similar 
> > problem with some leaked fd's in the LVM2 utilities -- I've not 
> > corresponded w/ that community ever, but I'll try to find them, 
> > too.)  But, I just wanted to share the workaround if anyone else was 
> > having trouble (seems unlikely).
> 
> Closing a larger set of FDs also really isn't the solution... If it 
> really is FD related, using dup2 rather than dup might be what's 
> called for.

It appears output-wrapper.cc is using dup2 everywhere, so I assume you 
mean in 'distcc'?  The dup's in the daemonization code there are around 
lines 586-595 of src/zeroconf.c:

http://code.google.com/p/distcc/source/browse/trunk/src/zeroconf.c#586

They use normal 'dup', and check for getting the desired fd num's via 
asserts, but in my own testing, std{in,out,err} are correctly 0, 1, and 
2 when run under outputwrapper.

-- 
Best,
Ben
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/wait.h>

void daemonize() {
	int fd, i;
	for (i = 0; i < 3; i++) close(i);
	fd = open("/dev/null", O_RDWR);
	assert(fd==0);
	fd = dup(0);
	assert(fd==1);
	fd = dup(0);
	assert(fd==2);
	setsid();
	chdir("/");
}

int main(void) {
	pid_t pid1,pid2;
	pid1 = fork();
	if (pid1 == -1) {
		// error in fork1
		_exit(1);
	} else if (pid1) {
		// parent
		waitpid(pid1, NULL, 0);
	} else {
		// child
		daemonize();
		pid2 = fork();
		if (pid2 == -1) {
			// error in fork2
			_exit(2);
		} else if (pid2) {
			// parent2
			_exit(3);
		} else {
			sleep(20);
			_exit(4);
		}
	}
	return 5;
}

_______________________________________________
paludis-user mailing list
[email protected]
http://lists.pioto.org/mailman/listinfo/paludis-user

Reply via email to