Klausur Maerz 2004 - Aufgabe 2

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

Klausur Maerz 2004 - Aufgabe 2

#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>
#include <stdio.h>
#include <signal.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/wait.h>



void pjob(char *mfile); 


static int anzahl = 0;
static int auftraege = 3;	
static int mmm = 0;
void sigchld_handler(int sig)
{
	pid_t pid;
	int status;
	while((pid = waitpid(-1, &status, WNOHANG)) > 0)
	{
		anzahl--;
	}

}



int main(int argc, char *argv[])
{
	int status;
	DIR *dir;
	struct dirent *ord;

	if(argc == 2)
	{
		auftraege = atoi(argv[1]);

	}
	printf("n: %i\n", auftraege);
		
	/*Siganlbehandlung fuer SIGCHLD*/
	struct sigaction sigchld;
	sigemptyset(&sigchld.sa_mask);
	sigchld.sa_flags = SA_RESTART; 
	sigchld.sa_handler = sigchld_handler;
	if(sigaction(SIGCHLD, &sigchld, NULL) == -1)
	{
		perror("sigchld");
		return -1;
	}
	
	dir = opendir("mailq2/");
	if(dir == NULL)
	{
		perror("opendir");
		return 1;
	}
	do
	{
		ord = readdir(dir);
		if(ord == NULL && errno != 0)
		{
			perror("readdir");
			return 1;
		}
		
		if(ord == NULL)
			break;
		if(ord->d_name[0] != 'm')
			continue;
		
		pjob(ord->d_name);
	}while(ord != NULL);
	
}

void pjob(char *mfile)
{
	printf("aufgerufen zum: %i\n", mmm++);
	pid_t pid; 
	sigset_t blocked_sigchld;
	sigset_t warten;
	sigemptyset(&warten); sigemptyset(&blocked_sigchld);
	sigaddset(&blocked_sigchld, SIGCHLD);
	if(sigprocmask(SIG_BLOCK, &blocked_sigchld, NULL) == -1)
	{
		perror("sigprocmask");
		exit(EXIT_FAILURE);
	}
	while(anzahl >= auftraege)
		sigsuspend(&warten);
	anzahl++;

	if(sigprocmask(SIG_UNBLOCK, &blocked_sigchld, NULL) == -1)
	{
		perror("sigprocmask");
		exit(EXIT_FAILURE);
	}

	
	switch(pid = fork()){
		case -1	: perror("fork"); exit(EXIT_FAILURE);
		case 0	:
			sleep(1);
                         exit(0);   /*<-- hinzugefuegt ...fehler ausgebessert funtzt jetzt */			
                        break;

	}

}

Hab mal versucht die Aufgabe 2 zu programmieren und bin bei dem sigsuspend haengen geblieben, weil die Prozesse nicht mehr sterben.

kann mir jemand weiterhelfen bzw. einen tipp gebeen?


http://fsi.informatik.uni-erlangen.de/forumtest/thread/3883

einen interessanten link … hab den code oben ein bisschen geaendert. Aber troztdem sterben die kinder nicht …naja …morgen nochmal schauen


ok hab meinen fehler gefunden und oben ausgebessert …exit(0) hingezugefuegt

falls es jemanden interessiert :smiley: … ich glaub ich leg mir noch einen zweiten account an …dann faellt es wenigstens nicht so auf, dass ich selbstgespraeche fuehre :vogel:


Ab morgen mach ich auch Programmieraufgaben…da du also vorgelegt hast würd ich mich auch direkt mal an der versuchen…


Ich hab die Aufgabe auch mal probiert, aber bisher nur auf dem Papier, noch nicht eingetippt. Ich hab die Synchronisation von den Semaphoren übernehmen lassen und dann gibt es imho gar keinen kritischen Bereich, in dem du SIGCHLD blockieren müsstest.

Ich ruf einfach vor dem fork() die P-Operation auf (ggf. solange, bis sie nicht mehr unterbrochen wird) und im handler für SIGCHLD die V-Operation. Mehr Koordinierungsaufwand dürfte doch gar nicht anfallen oder?

Rein theoretisch könnte man doch sogar auf das waitpid() verzichten, da ja nicht gefordert ist, sich um die Zombies zu kümmern (wobei es freilich schöner ist, es trotzdem zu tun).

pjob sieht bei mir recht einfach aus:

void pjob(char *mfile) {
   pid_t pid;

   while (P(&s) == -1);

   pid = fork();
   switch(pid) {
      case 0:
         send_mail(mfile);
         exit(EXIT_SUCCESS);
      case -1:
         perror("fork");
         exit(EXIT_FAILUE);
   }
}

nein, man muss fuer jedes waitpid, das einen Zombie erloest hat, eine
V-Operation durchfuehren. Es reicht nicht aus, pro SIGCHLD-handler-Aufruf
nur einmal V aufzurufen (es koennten ja, während er grade mal kurz
im SIGCHLD-handler ist mehrere Kinder sterben und dann wird nur ein
SIGCHLD gepuffer obwohl z.B. 3 Kinder gestorben sind. Er wuerde
in der Situation fuer 2 Kinder kein V aufrufen).

ja, so hatten wir es uns damals gedacht.
Die andere Loesung mit dem sigprocmask/sigsuspend ist genauso ok.