Exemple #1
0
void backup_terminated(int* fd){
	// Prepare the arguments in case the parent was terminated
	char arg1[10], arg2[10];
	int ret;
	ret = sprintf(arg1, "%s%d", "-n ", MAX_FORKS);
	if (ret < 0){
		perror("Error: sprintf could not write\n");
		return;
	}
	ret = sprintf(arg2, "%s%d", "-f ", fr);
	if (ret < 0){
		perror("Error: sprintf could not write\n");
		return;
	}
	
	// Try to write in the pipe
	char c[] = "test";

	ret = write(fd[1], c, strlen(c)+1);

	// Check if it was not possible to write there
	if(ret == -1){
		// Check if the read end was closed -> parent was terminated
		if(errno == EPIPE){
			logThis("Child detects the termination of its parent and will take the role as a backup process!\n", 0);
			logThis("---\n", 0);
			logThis("The state of its parent was:\n", 0);
			logThis("Max Forks = %d\n", MAX_FORKS);
			logThis("Fail Ratio = %d\n", fr);
			logThis("---\n", 0);
			logThis("-----------------------------RESTARTING-----------------------------\n", 0);
			execl("run", "run", arg1, arg2, (char*)0);
      		perror("Error: execl() failure!\n");
		} else
			perror("Error: Could not write even that the parent was not terminated!");
	}
}
Exemple #2
0
void logError(char *msg_)
{
    logThis(msg_);
    logThis("\n");
}
Exemple #3
0
int server(int fr, int* fd){
	// Reserve memory for reading request files
	char buffer[255];
	struct dirent* entry;
	int ret=0;
	while(1){
		// Open a directory stream of requests
		DIR *requestdir	= opendir("./requests");
		
		// Loop on each file in this directory
		while((entry = readdir(requestdir)) != NULL){
			// Check if the parent process was terminated, otherweise continue
			backup_terminated(fd);
			
			// Check if this file has only a regular type
			if (entry->d_type != DT_REG){
				continue;
			}
			
			// Open the file
			char filepath[100];
			strcpy(filepath, "requests/");
			strncat(filepath, entry->d_name, 22);
			FILE* requestFile = fopen(filepath, "r");
			if (requestFile == NULL){
				perror("Error: could not open file!\n");
				continue;
			}
			
			// Create artificial crash if specified by -f and filename contains "fail"
			const char failstr[10] = "fail";
			char* cret;
			cret = strstr(entry->d_name,failstr);
			if(fr > 0 && cret) {
				int r = rand() % 100;
				if (r >= fr) {
					printf("child process failed!\n");
					return -1;
				}
			}
			
			// Only read in first line (max 255 chars), since this is only pseudo code
			char* request = fgets(buffer, 255, requestFile);
			char msg[100];
			sprintf(msg,"server [%d] req: %s\n", getpid(), entry->d_name);
			logThis(msg,0);
			ret = usleep(500000);
			if (ret < 0){
				perror("Error: usleep failed!\n");
				return ret;
			}
			//close and delete request files
			ret = fclose(requestFile);
			if (ret != 0){
				perror("Error: could not close file!\n");
				continue;
			}
			ret = unlink(filepath);
			if (ret != 0){
				perror("Error: could not unlink!\n");
				continue;
			}
		}
		closedir(requestdir);;
	}
}
Exemple #4
0
int main(int argc, char** argv){
	printf("A nice welcome message\n");
	logThis("The program starts with a very nice welcome!\n", 0);
	int ret=0;

	int c; // Reserved for reading the program arguments
	int fd[2]; // Reserved for a pipe, the communication channel between parent and child
	
	// Parse inputs
	while ((c = getopt(argc, argv, "n:f:")) != -1){
		switch(c){
			case 'n':
				MAX_FORKS=atoi(optarg);
				if(MAX_FORKS < 1 || MAX_FORKS >50){
					ret = fprintf(stderr, "Illegal MAX_FORKS argument (%i), set MAX_FORKS to 5\n", MAX_FORKS);
					if (ret < 0){
						perror("Error: fprintf could not write\n");
						return ret;
					}
					MAX_FORKS=5;
				}
				break;
			case 'f':
				fr = atoi(optarg);
				if (fr < 0 || fr > 100) {
					ret = fprintf(stderr, "Illegal failratio argument (%i), set failratio to 0\n", fr);
					if (ret < 0){
						perror("Error: fprintf could not write\n");
						return ret;
					}
					fr=0;
				}
				break;
			default:
				ret = fprintf(stderr, "Unknown or syntactically erroneous parameter\n");
				if (ret < 0){
					perror("Error: fprintf could not write\n");
					return ret;
				}
		}
	}

	// Logging program arguments
	logThis("---\n", 0);
	logThis("The program has the following arguments:\n", 0);
	logThis("Max Forks = %d\n", MAX_FORKS);
	logThis("Fail Ratio = %d\n", fr);
	logThis("---\n", 0);
	
	// Start creating processes
	backup(MAX_FORKS, fd);
	
	// Init rng after backup has been done to get different seeds
	srand(getpid());
	
	printf("start processing requests\n");
	ret = server(fr, fd);
	
	printf("done processing\n");
	exit(ret);
}
Exemple #5
0
int backup(int MAX_FORKS, int* fd) {
	int pid;
	int status;
	int sleep_status;
	int printParentID = 1; // will be used to check if parent ID was logged
	int num_forks = 0;

	// Create primary processes and wait in case they fail
	while(1){
		// Count number of attempts at child creation
		num_forks+=1;
		
		// Create a pipe to be used as a channel between parent and its child
		int ret = pipe(fd);
		// Check if error raise
		if(ret == -1){
			perror("Error: error when creating a pipe");
			return ret;
		}

		// Ignore the signal and check if signal doesn't fail
		signal(SIGPIPE, SIG_IGN);
		if(errno == EINVAL){
			perror("Error: signal() fails; signum is invalid");
			return -1;
		}

		printf("creating child...\n");
		pid = fork();

		// Handle fork error
		if(pid < 0) {
			perror("Error: error when creating a child");
		}

		// Child process (primary)
		if(pid == 0) {
			// The child closes the write end of the pipe
			if(close(fd[0])){
				perror("Error: close() raises an error while closing write end of the pipe!");
			}

			printf("I am the child process with pid %i\n", getpid());
			logThis("A new child process created with ID = %i\n", getpid());

			//return to start request processing
			return 0;
		}
		else if(pid < 0 && num_forks > MAX_FORKS){
			// Gracefully degrade and start request processing without backup
			printf("I am the parent process with pid %i\n",getpid());
			perror("Maximum number of retries to create child exceeded, backup process is now doing processing");
			return pid;
		}

		printf("I am the parent process with pid %i\n",getpid());
		
		// Check if the parent ID was not printed in the log file
		if(printParentID){
			logThis("The parent process has ID = %i\n", getpid());
			printParentID = 0;
		}
		
		// The parent closes the read end of the pipe, check if any error raises
		if(close(fd[1])){
			perror("Error: close() raises an error while closing the read end of the pipe!");
		}

		// Wait for crash of primary
		printf("waiting %i\n", pid);
		pid = waitpid((pid_t)pid, &status, 0);
		if(pid < 0){
			perror("Error: while trying to wait for child");
		}

		printf("done waiting%i\n", pid);
	}
	return 0;
}