Optimizing SIGCHLD Handler for Prime Number Generation

  • Thread starter Thread starter TylerH
  • Start date Start date
AI Thread Summary
The program generates a complete list of prime numbers using worker processes to check the primality of individual numbers. The SIGCHLD handler is registered to manage the termination of child processes, but it initially hangs due to issues with accessing and erasing elements from the `procs` map. The problem was resolved by moving the waiting logic to the function that requires the results from the child processes. The discussion then shifts to optimizing memory usage, specifically regarding Copy-On-Write (COW) pages, with inquiries about their behavior during parent and child writes. The goal is to minimize memory duplication while ensuring that only one copy of the prime list is maintained, as child processes do not modify this list.
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.
 
Technology 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.)
 
Dear Peeps I have posted a few questions about programing on this sectio of the PF forum. I want to ask you veterans how you folks learn program in assembly and about computer architecture for the x86 family. In addition to finish learning C, I am also reading the book From bits to Gates to C and Beyond. In the book, it uses the mini LC3 assembly language. I also have books on assembly programming and computer architecture. The few famous ones i have are Computer Organization and...
I have a quick questions. I am going through a book on C programming on my own. Afterwards, I plan to go through something call data structures and algorithms on my own also in C. I also need to learn C++, Matlab and for personal interest Haskell. For the two topic of data structures and algorithms, I understand there are standard ones across all programming languages. After learning it through C, what would be the biggest issue when trying to implement the same data...

Similar threads

Replies
8
Views
5K
Replies
36
Views
262
Replies
4
Views
5K
Replies
3
Views
5K
Replies
6
Views
7K
Replies
14
Views
4K
Replies
8
Views
9K
Replies
11
Views
3K
Back
Top