static void john_mpi_wait(void) { if (!database.password_count && !options.reload_at_crack) { int i; for (i = 0; i < mpi_p; i++) { if (i == mpi_id) continue; if (mpi_req[i] == NULL) mpi_req[i] = mem_alloc_tiny(sizeof(MPI_Request), MEM_ALIGN_WORD); else if (*mpi_req[i] != MPI_REQUEST_NULL) continue; MPI_Isend("r", 1, MPI_CHAR, i, JOHN_MPI_RELOAD, MPI_COMM_WORLD, mpi_req[i]); } } if (john_main_process) { log_event("Waiting for other node%s to terminate", mpi_p > 2 ? "s" : ""); fprintf(stderr, "Waiting for other node%s to terminate\n", mpi_p > 2 ? "s" : ""); mpi_teardown(); } /* Close and possibly remove our .rec file now */ rec_done(!event_abort ? -1 : -2); }
static void john_fork(void) { int i, pid; int *pids; fflush(stdout); fflush(stderr); #if HAVE_MPI /* * We already initialized MPI before knowing this is actually a fork session. * So now we need to tear that "1-node MPI session" down before forking, or * all sorts of funny things might happen. */ mpi_teardown(); #endif /* * It may cost less memory to reset john_main_process to 0 before fork()'ing * the children than to do it in every child process individually (triggering * copy-on-write of the entire page). We then reset john_main_process back to * 1 in the parent, but this only costs one page, not one page per child. */ john_main_process = 0; pids = mem_alloc_tiny((options.fork - 1) * sizeof(*pids), sizeof(*pids)); for (i = 1; i < options.fork; i++) { switch ((pid = fork())) { case -1: pexit("fork"); case 0: sig_preinit(); options.node_min += i; options.node_max = options.node_min; #if HAVE_OPENCL // Poor man's multi-device support if (options.gpu_devices->count && strstr(database.format->params.label, "-opencl")) { // Pick device to use for this child opencl_preinit(); gpu_id = gpu_device_list[i % get_number_of_devices_in_use()]; platform_id = get_platform_id(gpu_id); // Hide any other devices from list gpu_device_list[0] = gpu_id; gpu_device_list[1] = -1; // Postponed format init in forked process fmt_init(database.format); } #endif if (rec_restoring_now) { unsigned int node_id = options.node_min; rec_done(-2); rec_restore_args(1); if (node_id != options.node_min + i) fprintf(stderr, "Inconsistent crash recovery file:" " %s\n", rec_name); options.node_min = options.node_max = node_id; } sig_init_child(); return; default: pids[i - 1] = pid; } } #if HAVE_OPENCL // Poor man's multi-device support if (options.gpu_devices->count && strstr(database.format->params.label, "-opencl")) { // Pick device to use for mother process opencl_preinit(); gpu_id = gpu_device_list[0]; platform_id = get_platform_id(gpu_id); // Hide any other devices from list gpu_device_list[1] = -1; // Postponed format init in mother process fmt_init(database.format); } #endif john_main_process = 1; john_child_pids = pids; john_child_count = options.fork - 1; options.node_max = options.node_min; }
void rec_restore_args(int lock) { char line[LINE_BUFFER_SIZE]; int index, argc; char **argv; char *save_rec_name; rec_name_complete(); if (!(rec_file = fopen(path_expand(rec_name), "r+"))) { #ifndef HAVE_MPI if (options.fork && !john_main_process && errno == ENOENT) { #else if (options.node_min > 1 && errno == ENOENT) { #endif fprintf(stderr, "%u Session completed\n", options.node_min); if (options.flags & FLG_STATUS_CHK) return; log_event("No crash recovery file, terminating"); log_done(); #ifdef HAVE_MPI mpi_teardown(); #endif exit(0); } #ifdef HAVE_MPI if (mpi_p > 1) { fprintf(stderr, "%u@%s: fopen: %s: %s\n", mpi_id + 1, mpi_name, path_expand(rec_name), strerror(errno)); error(); } #endif pexit("fopen: %s", path_expand(rec_name)); } rec_fd = fileno(rec_file); if (lock) rec_lock(lock); if (!fgetl(line, sizeof(line), rec_file)) rec_format_error("fgets"); rec_version = 0; if (!strcmp(line, RECOVERY_V4)) rec_version = 4; else if (!strcmp(line, RECOVERY_V3)) rec_version = 3; else if (!strcmp(line, RECOVERY_V2)) rec_version = 2; else if (!strcmp(line, RECOVERY_V1)) rec_version = 1; else if (strcmp(line, RECOVERY_V0)) rec_format_error(NULL); if (fscanf(rec_file, "%d\n", &argc) != 1) rec_format_error("fscanf"); if (argc < 2) rec_format_error(NULL); argv = mem_alloc_tiny(sizeof(char *) * (argc + 1), MEM_ALIGN_WORD); argv[0] = "john"; for (index = 1; index < argc; index++) if (fgetl(line, sizeof(line), rec_file)) argv[index] = str_alloc_copy(line); else rec_format_error("fgets"); argv[argc] = NULL; save_rec_name = rec_name; opt_init(argv[0], argc, argv, 0); rec_name = save_rec_name; rec_name_completed = 1; if (fscanf(rec_file, "%u\n%u\n%x\n%x\n", &status_restored_time, &status.guess_count, &status.combs.lo, &status.combs.hi) != 4) rec_format_error("fscanf"); if (!status_restored_time) status_restored_time = 1; if (rec_version >= 4) { if (fscanf(rec_file, "%x\n%x\n%x\n%x\n%x\n%d\n", &status.combs_ehi, &status.crypts.lo, &status.crypts.hi, &status.cands.lo, &status.cands.hi, &status.compat) != 6) rec_format_error("fscanf"); } else { /* Historically, we were reusing what became the combs field for candidates * count when in --stdout mode */ status.cands = status.combs; status.compat = 1; } if (rec_version == 0) { status.pass = 0; status.progress = -1; } else if (fscanf(rec_file, "%d\n%d\n", &status.pass, &status.progress) != 2) rec_format_error("fscanf"); if (status.pass < 0 || status.pass > 3) rec_format_error(NULL); if (rec_version < 3) rec_check = 0; else if (fscanf(rec_file, "%x\n", &rec_check) != 1) rec_format_error("fscanf"); rec_restoring_now = 1; } void rec_restore_mode(int (*restore_mode)(FILE *file)) { rec_name_complete(); if (!rec_file) return; if (restore_mode) if (restore_mode(rec_file)) rec_format_error("fscanf"); if (options.flags & FLG_MASK_STACKED) if (mask_restore_state(rec_file)) rec_format_error("fscanf"); /* * Unlocking the file explicitly is normally not necessary since we're about to * close it anyway (which would normally release the lock). However, when * we're the main process running with --fork, our newborn children may hold a * copy of the fd for a moment (until they close the fd themselves). Thus, if * we don't explicitly remove the lock, there may be a race condition between * our children closing the fd and us proceeding to re-open and re-lock it. */ rec_unlock(); if (fclose(rec_file)) pexit("fclose"); rec_file = NULL; rec_restoring_now = 0; }