Optimizing SIGCHLD Handler for Prime Number Generation

  • Thread starter Thread starter TylerH
  • Start date Start date
Join the discussion
Registration is free. Ask a follow-up in this thread, or start your own.
2 replies · 2K views
TylerH
Messages
729
Reaction score
0
My program is generating a complete, ordered list of primes and children are the worker processes deciding the primality of a single number and exiting with true iff the number they are assigned it prime. The map procs maps pids to numbers being checked.

Here is where I register the handler:
Code:
	struct sigaction sa;
	sa.sa_handler = sigchld_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_NOCLDSTOP;
	if (sigaction(SIGCHLD, &sa, NULL) < 0) {
		perror("sigaction");
		exit(1);
	}

Here is my handler:
Code:
void sigchld_handler(int signal){
	int status;
	pid_t pid;
	
	cout << "Entered handler." << endl;
	while((pid = wait(&status)) > 0){
		cout << "Entered loop." << endl;
		if(!WIFEXITED(status)){
			cerr << "Error: " << pid << " exited abnormally." << endl;
			exit(1);
		}
		auto n = procs.find(pid)->second;
		procs.erase(pid);
		cout << "1" << endl;
		if(status){
			cout << "Tested true: " << n << endl;
			buffer.insert(n);
		}
		else
			cout << "Tested false: " << n << endl;
		cout << "2" << endl;
		bool min = true;
		while(min && !buffer.empty()){
			mpz_class n = *buffer.begin();
			for(auto i = procs.begin();(min = mpz_class(i->second) > n) && i != procs.end();i++);
			if(min){
				primes.push_back(n);
				cout << "Added: " << n << endl;
				buffer.erase(n);
			} else
				cout << "Buffered: " << n << endl;
		}
	}
	/*if(pid != ECHILD){
		cerr << "Error: wait() returned negative other than ECHILD" << endl;
		exit(1);
	}*/
}

When the program is ran, the only output I get is:
Entered handler.
Entered loop.
1
[hang, as in, nothing is printed and it doesn't exit]

ps -a on another terminal prints:
10304 pts/0 00:00:00 a.out
10306 pts/0 00:00:00 a.out <defunct>
10307 pts/0 00:00:00 a.out <defunct>
10308 pts/0 00:00:00 a.out <defunct>
10310 pts/1 00:00:00 ps

I'd be glad to post the rest of the code for anyone who thinks it could be the culprit, I just didn't want to bombard you with code that probably (I assume) isn't helpful.
 
Physics news on Phys.org
Are you using a debugger? Since you're seeing "Entered handler" and "Entered loop", but not seeing "1", or "Error <pid> exited abnormally", it would seem that something untoward is happening in this code:
Code:
auto n = procs.find(pid)->second;
procs.erase(pid);
 
I still don't really know what was going wrong, but I suppose it probably had to do with my false assumption that signals are queued.

I fixed it by doing the waiting in the function in which the results of the child processes are needed. It works now, so I'd like to start optimizing it. Is there any way to analyze how many/which COW pages are being copied? Are COW pages copied when the parent writes or only when the child does it? If they're copied when the parent writes to them, it there any way to disable this or get a chuck of memory which doesn't do this? For context, I only want 1 copy of the list of all primes, to keep memory waste to a minimum. I know children will never write to the list, because they are guaranteed to have all the primes they need to complete their check. (From 2 to sqrt(n), where n is the number being checked.)