/* Notify the user about stopped or terminated jobs. Delete terminated jobs from the active job list. */ void do_job_notification (void) { job *j, *jlast, *jnext; process *p; /* Update status information for child processes. */ update_status (); jlast = NULL; for (j = first_job; j; j = jnext) { jnext = j->next; /* If all processes have completed, tell the user the job has completed and delete it from the list of active jobs. */ if (job_is_completed (j)) { format_job_info (j, "completed"); if (jlast) jlast->next = jnext; else first_job = jnext; free_job (j); } /* Notify the user about stopped jobs, marking them so that we won’t do this more than once. */ else if (job_is_stopped (j) && !j->notified) { format_job_info (j, "stopped"); j->notified = 1; jlast = j; } /* Don’t say anything about jobs that are still running. */ else jlast = j; } }
/** Free the jobs and job_teams arrays. */ void free_jobs(gboolean reset) { #ifdef DEBUG printf("free_jobs\n"); #endif gint i; if(jobs == NULL) { if(reset) { jobs = g_array_new(FALSE, FALSE, sizeof(Job)); job_teams = g_array_new(FALSE, FALSE, sizeof(Team)); } return; } for(i=0; i<jobs->len; i++) free_job(&g_array_index(jobs, Job, i), TRUE); free_g_array(&jobs); free_g_array(&job_teams); if(reset) { jobs = g_array_new(FALSE, FALSE, sizeof(Job)); job_teams = g_array_new(FALSE, FALSE, sizeof(Team)); } }
void remove_and_free(job_t *j){ job_t * prev = find_prev_job(j); if(!prev){ //must be first job if(first_job != j) perror("wrong pgid"); job_t * tmp = first_job; if (first_job->next) first_job = first_job->next; free_job(tmp); return; } if (j->next) { job_t * tmp; tmp = j->next; j->next = tmp->next; free_job(tmp); } }
void free_job(job *j) { if(!j) return; free_job(j->next); free_process(j->process_list); free(j); }
/** Free any memory associated with your scheduler. Assumptions: - This function will be the last function called in your library. */ void scheduler_clean_up() { void* p = NULL; while( (p = priqueue_poll(jobs)) != NULL ) free_job((job_t*)p); priqueue_destroy(jobs); free(jobs); free_core(&cores); }//scheduler_clean_up
/* delete a given job j; We will simply loop from first_job since we do not * store prev pointer */ void delete_job(job_t *j, job_t *first_job){ if(!j || !first_job) return; job_t *first_job_itr = first_job; if(first_job_itr == j) { /* header */ free_job(j); first_job = NULL; /* reinitialize for later purposes */ return; } /* not header */ while(first_job_itr->next != NULL) { if(first_job_itr->next == j) { first_job_itr->next = first_job_itr->next->next; free_job(j); return; } first_job_itr = first_job_itr->next; } }
/* Remove job from jobs list and free it. */ bool remove_job(job_t* job) { if (!first_job) { return false; } else if (first_job == job) { first_job = job->next; return free_job(job); } else { job_t *j = first_job; while (j && j->next != job) j = j->next; if (j) { j->next = job->next; return free_job(job); } return false; } }
/** Wait on fg job **/ void jwait(job *j) { if (j == NULL) return; //printf("Waiting on %s (j->running = %d)...\n", j->rawcmd, j->running); while(j->running) pause(); if(j->complete) { free_job(del_job(job_list, j->pgid)); } }
int main (int argc, char **argv, char **env) { argc = argc; argv = argv; env = env; char *result, *error; char cmd[120]; int x; /* set hostname */ gethostname(hostname, GM_BUFFERSIZE-1); /* create options structure and set debug level */ mod_gm_opt = malloc(sizeof(mod_gm_opt_t)); set_default_options(mod_gm_opt); mod_gm_opt->debug_level = 4; #ifdef EMBEDDEDPERL char p1[150]; snprintf(p1, 150, "--p1_file=worker/mod_gearman2_p1.pl"); parse_args_line(mod_gm_opt, p1, 0); init_embedded_perl(env); #endif gm_job_t * exec_job; exec_job = ( gm_job_t * )malloc( sizeof *exec_job ); set_default_job(exec_job, mod_gm_opt); strcpy(cmd, "BLAH=BLUB /bin/hostname"); printf("this should be popen\n"); run_check(cmd, &result, &error); free(result); free(error); strcpy(cmd, "/bin/hostname"); printf("this should be execvp\n"); run_check(cmd, &result, &error); free(result); free(error); mod_gm_opt->debug_level = 0; for(x=0;x<100;x++) { run_check(cmd, &result, &error); free(result); free(error); } free_job(exec_job); mod_gm_free_opt(mod_gm_opt); #ifdef EMBEDDEDPERL deinit_embedded_perl(0); #endif exit(0); }
static void free_flexsched_problem(flexsched_problem_t flex_prob) { int i; if (!flex_prob) return; for (i = 0; i < flex_prob->num_nodes; i++) { free_node(flex_prob->nodes[i]); } free(flex_prob->nodes); for (i = 0; i < flex_prob->num_jobs; i++) { free_job(flex_prob->jobs[i]); } free(flex_prob->jobs); free(flex_prob); }
void finish_job(){ if(current_job == NULL){ return; } if(get_receiver_connection_number(receiver_connection_head) != 0){ return; } if(get_not_found_chunk_number(current_job) != 0){ return; } printf("GOT %s\n", current_job->output_file_name); free_job(current_job); current_job = NULL; }
static void freectx (void *arg) { ctx_t *ctx = arg; free_simstate (ctx->sim_state); while (zlist_size (ctx->queued_events) > 0) free (zlist_pop (ctx->queued_events)); zlist_destroy (&ctx->queued_events); while (zlist_size (ctx->running_jobs) > 0) free_job (zlist_pop (ctx->running_jobs)); zlist_destroy (&ctx->running_jobs); rdllib_close (ctx->rdllib); free (ctx->rdl); free (ctx); }
static void job_exit_callback(Job *job) { // Free the slot now, 'exit_cb' may want to start another job to replace // this one table[job->id - 1] = NULL; if (job->exit_cb) { // Invoke the exit callback job->exit_cb(job, job->data); } // Free the job resources free_job(job); // Stop polling job status if this was the last job_count--; if (job_count == 0) { uv_prepare_stop(&job_prepare); } }
void init_job(void) { /* Background */ max = 2; end = 1; job = malloc(sizeof(struct job *) * max); if (!job) { fprintf(stderr, "init_job: malloc error\n"); exit(-1); } /* Foreground */ job[0] = malloc(sizeof(struct job)); if (!job[0]) { fprintf(stderr, "init_job: init foreground process failed!\n"); free_job(); exit(-1); } job[0]->command = NULL; }
/** Called when a job has completed execution. The core_id, job_number and time parameters are provided for convenience. You may be able to calculate the values with your own data structure. If any job should be scheduled to run on the core free'd up by the finished job, return the job_number of the job that should be scheduled to run on core core_id. @param core_id the zero-based index of the core where the job was located. @param job_number a globally unique identification number of the job. @param time the current time of the simulator. @return job_number of the job that should be scheduled to run on core core_id @return -1 if core should remain idle. */ int scheduler_job_finished(int core_id, int job_number, int time) { // Increment Time inc_time(time); // Process job termination job_t* p = delete_job(core_id,job_number); priqueue_remove(jobs,p); inc_wait(cur_t - p->arr_t - p->run_t); inc_turn(cur_t - p->arr_t); free_job(p); // Schedule new job p = priqueue_poll(jobs); if ( p != NULL ) { insert_job(core_id,p); return p->jid; }//if return -1; }//scheduler_job_finished
void * tfn7(void * arg) { int count; Job task = (struct job *)malloc(sizeof(struct job)); task->next = NULL; task->val = 0; task->tid = -1; pthread_t tid = pthread_self(); count = 0; while (count < MAX_ITEM) { if (pthread_mutex_trylock(&q_lock) == 0) { get_job(arg, task, &count, tid); pthread_mutex_unlock(&q_lock); } } print(task); if (free_job(task) == -1) { exit(1); } return (void *)0; }
void * tfn7(void * arg) { int count; /* 每次取得链表结点数 */ struct job * task = NULL; /* 属于当前线程的任务结点的队列头 */ pthread_t tid; tid = pthread_self(); /* 得到当前线程ID,根据此线程ID判断任务是否归属于当前线程 */ count = 0; while(count < MAX_ITEM) if(pthread_mutex_trylock(&q_lock) == 0) { /* 将队列加锁 */ get_job((Job) arg, task, &count); pthread_mutex_unlock(&q_lock); /* 遍历链表结束,释放锁 */ } print((Job) arg); if(free_job(task) == -1) exit(1); return (void *)0; }
static int deal_with_int(t_shell *sh, t_job *job, t_parse *parse) { int i; int j; i = 0; j = 1; while (parse->argv[j][i]) { if (parse->argv[j][i] < '0' || parse->argv[j][i] > '9') { ft_putendl_fd("exit: Badly formed number.", 2); return (1); } i++; } i = ft_atoi(parse->argv[1]); free_job(job); free_parse(&parse); reset_term(sh); exit(i); }
// Update sched timer as necessary (to trigger an event in sched) // Also change the state of the job in the KVS static int complete_job (ctx_t *ctx, job_t *job, double completion_time) { flux_t *h = ctx->h; int rc; flux_log (h, LOG_INFO, "Job %d completed", job->id); update_job_state (ctx, job->id, job->kvs_dir, J_COMPLETE, completion_time); set_event_timer (ctx, "sched", ctx->sim_state->sim_time + .00001); rc = set_job_timestamps (job->kvs_dir, SIM_TIME_NONE, // starting SIM_TIME_NONE, // running SIM_TIME_NONE, // completing completion_time, job->io_time); if (rc < 0) flux_log_error (h, "%s: set_job_timestamps", __FUNCTION__); free_job (job); return rc; }
int do_exit(t_shell *sh, t_job *job, t_parse *parse) { int i; i = 1; if (!parse->argv[i]) { free_job(job); free_parse(&parse); reset_term(sh); exit(0); } while (parse->argv[i]) i++; if (i > 2) { ft_putendl_fd("exit: Expression Syntax.", 2); return (1); } else if (deal_with_int(sh, job, parse) == 1) return (1); return (0); }
int main(int argc, char ** argvFILE) { char line[1024]; /* the input line */ char *argv[64]; /* the command line argument */ char * p; int tokens, foreground; int * ptokens =&tokens; int * pforeground =&foreground; int input_from_file = ftell(stdin); /* check if input is coming from file */ init_shell(); while (1) { /* repeat until done .... */ if(input_from_file < 0) /* stdin is coming from user not file */ printf("sish:>"); /* display a prompt */ memset (line, '\0', sizeof(line)); // zero line, (fills array with null terminator) memset (argv, '\0', sizeof(argv)); if (!fgets(line, sizeof(line), stdin)) {printf("\n"); return 0;} // Exit upon ctrl-D if(strlen(line) == 1) { continue; // check for empty string aka 'enter' is pressed without input } if ((p = strchr(line, '\n')) != NULL) // remove '\n' from the end of 'line' *p = '\0'; parse (line, argv, ptokens); // parse input to shell if (argv[0] == '\0') continue; else if (strcmp(argv[0], "exit") == 0) /* is it an "exit"? */ return 0; /* exit if it is */ else if (strcmp(argv[0], "cd") == 0) cd (argv[1]); else { if ((first_job = job_initialize(argv, tokens, pforeground)) != NULL) { launch_job (first_job, foreground); free_job(first_job); } } } }
void exec_job(t_shell *sh, t_job *job) { t_job *tmp; tmp = job; reset_term_no_free(sh); while (job) { launch_process(sh, job); if (!job_success(job) && job->linker == AND) { while (job->next && job->linker == AND) job = job->next; } else if (job_success(job) && job->linker == OR) { while (job->next && job->linker == OR) job = job->next; } job = job->next; } job = tmp; free_job(job); }
bool invokefree(job_t *j, char *msg){ fprintf(stderr, "%s\n",msg); return free_job(j); }
/* * builtin_cmd - If the user has typed a built-in command then execute * it immediately. */ bool builtin_cmd(job_t *last_job, int argc, char **argv) { /* check whether the cmd is a built in command */ if (!strcmp("quit", argv[0])) { /* Your code here */ exit(EXIT_SUCCESS); } else if (!strcmp("jobs", argv[0])) { /* Your code here */ job_t* currentJob = active_jobs_head; job_t* deletedJob = NULL; while(currentJob != NULL) { // print active jobs and then change notified to 0 //if((currentJob->first_process)->completed == true && currentJob->notified == false) { //need to check if every process has completed for a job to be complete, not just the first process if (job_is_completed(currentJob) == true) { printf("%d (Completed): %s\n", currentJob->pgid, currentJob->commandinfo); deletedJob = currentJob; //currentJob->notified = true; } //otherwise it is stopped else if (job_is_stopped(currentJob) == true) { printf("%d (Stopped): %s\n", currentJob->pgid, currentJob->commandinfo); } else { printf("%d (Running): %s\n", currentJob->pgid, currentJob->commandinfo); } currentJob = currentJob->next; // delete job after it is completed, don't need to save notified if (deletedJob != NULL) { if (deletedJob == active_jobs_head) { active_jobs_head = deletedJob->next; free_job(deletedJob); //TBD warning about this? } else { delete_job(deletedJob, active_jobs_head); } deletedJob = NULL; } } return true; } else if (!strcmp("cd", argv[0])) { int chdir_return = chdir(argv[1]); if(chdir_return == -1) { printf("cd: %s: No such file or directory\n", argv[1]); } return true; } else if (!strcmp("bg", argv[0])) { /* Your code here */ job_t* currentJob = active_jobs_head; process_t* p2; if(argv[1] == NULL) { // continue most recent stopped job //use find_last_job currentJob = find_last_job(active_jobs_head); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while(p2 != NULL) { p2->stopped = false; struct sigaction action; action.sa_sigaction = sighandler; sigfillset(&action.sa_mask); action.sa_flags = SA_SIGINFO; sigaction(SIGCHLD, &action, NULL); p2 = p2->next; } seize_tty(getpid()); } else { pid_t job_number = atoi(argv[1]); while(currentJob != NULL) { // Need to eventually iterate through all processes? if((job_is_stopped(currentJob)) && currentJob->pgid == job_number) { //seize_tty(currentJob->pgid); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while (p2 != NULL) { p2->stopped = false; struct sigaction action; action.sa_sigaction = sighandler; sigfillset(&action.sa_mask); action.sa_flags = SA_SIGINFO; sigaction(SIGCHLD, &action, NULL); p2 = p2->next; } seize_tty(getpid()); break; } else if (currentJob->pgid == job_number) { printf("%s\n", "This process wasn't stopped`"); } else { printf("%s\n", "This job number is not the requested one"); } currentJob = currentJob->next; } } return true; } else if (!strcmp("fg", argv[0])) { /* Your code here */ job_t* currentJob = active_jobs_head; process_t* p2; if(argv[1] == NULL) { // continue most recent stopped job //use find_last_job currentJob = find_last_job(active_jobs_head); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while(p2 != NULL) { waiting(p2); p2 = p2->next; } seize_tty(getpid()); } else { pid_t job_number = atoi(argv[1]); while(currentJob != NULL) { if((job_is_stopped(currentJob)) && currentJob->pgid == job_number) { //seize_tty(currentJob->pgid); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while (p2 != NULL) { waiting(p2); p2 = p2->next; } seize_tty(getpid()); break; } else if (currentJob->pgid == job_number) { printf("%s\n", "This process wasn't stopped`"); } else { printf("%s\n", "This job number is not the requested one"); } currentJob = currentJob->next; } } return true; } /* not a builtin command */ return false; }
/* get a job */ void *get_job( gearman_job_st *job, void *context, size_t *result_size, gearman_return_t *ret_ptr ) { sigset_t block_mask; int wsize, valid_lines; char workload[GM_BUFFERSIZE]; char * decrypted_data; char * decrypted_data_c; char * decrypted_orig; char *ptr; /* reset timeout for now, will be set befor execution again */ alarm(0); signal(SIGALRM, SIG_IGN); jobs_done++; /* send start signal to parent */ set_state(GM_JOB_START); gm_log( GM_LOG_TRACE, "get_job()\n" ); /* contect is unused */ context = context; /* set size of result */ *result_size = 0; /* reset sleep time */ sleep_time_after_error = 1; /* ignore sigterms while running job */ sigemptyset(&block_mask); sigaddset(&block_mask, SIGTERM); sigprocmask(SIG_BLOCK, &block_mask, NULL); /* get the data */ current_gearman_job = job; wsize = gearman_job_workload_size(job); strncpy(workload, (const char*)gearman_job_workload(job), wsize); workload[wsize] = '\0'; gm_log( GM_LOG_TRACE, "got new job %s\n", gearman_job_handle( job ) ); gm_log( GM_LOG_TRACE, "%d +++>\n%s\n<+++\n", strlen(workload), workload ); /* decrypt data */ decrypted_data = malloc(GM_BUFFERSIZE); decrypted_data_c = decrypted_data; mod_gm_decrypt(&decrypted_data, workload, mod_gm_opt->transportmode); decrypted_orig = strdup(decrypted_data); if(decrypted_data == NULL) { *ret_ptr = GEARMAN_WORK_FAIL; free(decrypted_orig); return NULL; } gm_log( GM_LOG_TRACE, "%d --->\n%s\n<---\n", strlen(decrypted_data), decrypted_data ); /* set result pointer to success */ *ret_ptr= GEARMAN_SUCCESS; exec_job = ( gm_job_t * )malloc( sizeof *exec_job ); set_default_job(exec_job, mod_gm_opt); valid_lines = 0; while ( (ptr = strsep(&decrypted_data, "\n" )) != NULL ) { char *key = strsep( &ptr, "=" ); char *value = strsep( &ptr, "\x0" ); if ( key == NULL ) continue; if ( value == NULL || !strcmp( value, "") ) break; if ( !strcmp( key, "host_name" ) ) { exec_job->host_name = strdup(value); valid_lines++; } else if ( !strcmp( key, "service_description" ) ) { exec_job->service_description = strdup(value); valid_lines++; } else if ( !strcmp( key, "type" ) ) { exec_job->type = strdup(value); valid_lines++; } else if ( !strcmp( key, "result_queue" ) ) { exec_job->result_queue = strdup(value); valid_lines++; } else if ( !strcmp( key, "check_options" ) ) { exec_job->check_options = atoi(value); valid_lines++; } else if ( !strcmp( key, "scheduled_check" ) ) { exec_job->scheduled_check = atoi(value); valid_lines++; } else if ( !strcmp( key, "reschedule_check" ) ) { exec_job->reschedule_check = atoi(value); valid_lines++; } else if ( !strcmp( key, "latency" ) ) { exec_job->latency = atof(value); valid_lines++; } else if ( !strcmp( key, "next_check" ) ) { string2timeval(value, &exec_job->next_check); valid_lines++; } else if ( !strcmp( key, "start_time" ) ) { /* for compatibility reasons... (used by older mod-gearman neb modules) */ string2timeval(value, &exec_job->next_check); string2timeval(value, &exec_job->core_time); valid_lines++; } else if ( !strcmp( key, "core_time" ) ) { string2timeval(value, &exec_job->core_time); valid_lines++; } else if ( !strcmp( key, "timeout" ) ) { exec_job->timeout = atoi(value); valid_lines++; } else if ( !strcmp( key, "command_line" ) ) { exec_job->command_line = strdup(value); valid_lines++; } } #ifdef GM_DEBUG if(exec_job->next_check.tv_sec < 10000) write_debug_file(&decrypted_orig); #endif if(valid_lines == 0) { gm_log( GM_LOG_ERROR, "discarded invalid job (%s), check your encryption settings\n", gearman_job_handle( job ) ); } else { do_exec_job(); } current_gearman_job = NULL; /* start listening to SIGTERMs */ sigprocmask(SIG_UNBLOCK, &block_mask, NULL); free(decrypted_orig); free(decrypted_data_c); free_job(exec_job); /* send finish signal to parent */ set_state(GM_JOB_END); if(mod_gm_opt->max_jobs > 0 && jobs_done >= mod_gm_opt->max_jobs) { gm_log( GM_LOG_TRACE, "jobs done: %i -> exiting...\n", jobs_done ); clean_worker_exit(0); _exit( EXIT_SUCCESS ); } return NULL; }
void test_mm(void) { int max_threads = 8; thread_pool_t *thread_pool = create_thread_pool(max_threads); int m = 8192; int n = 1024; int k = 1024; double *a = make_array(m, k); double *b = make_array(k, n); double *o = make_array(m, n); int tile_sizes[5] = {1024, 64, 64, 8, 8}; int num_threads = 8; job_t *job = make_job(0, m, 1024, num_threads, 1); vm_args_t vm_args; vm_args.a = a; vm_args.b = b; vm_args.out = o; vm_args.m = m; vm_args.n = n; vm_args.k = k; struct timeval start, end, result; gettimeofday(&start, NULL); launch_job(thread_pool, &vm2, &vm_args, job, tile_sizes, 1); wait_for_job(thread_pool); gettimeofday(&end, NULL); double t; timersub(&end, &start, &result); t = result.tv_sec + result.tv_usec / 1000000.0; printf("Parallel runtime: %f\n", t); int pass = 1; // int i, j, l; // double sum; // gettimeofday(&start, NULL); // for (i = 0; i < m; ++i) { // for (j = 0; j < n; ++j) { // sum = 0.0; // for (l = 0; l < k; ++l) { // sum += a[i*k + l] * b[j*k + l]; // } // pass = pass && (abs(sum - o[i*n + j]) < 1e-4); // } // } // gettimeofday(&end, NULL); CU_ASSERT(pass); // double naive_time; // timersub(&end, &start, &result); // naive_time = result.tv_sec + result.tv_usec / 1000000.0; // printf("Naive time: %f\n", naive_time); destroy_thread_pool(thread_pool); free_job(job); free_array(a); free_array(b); free_array(o); }
int main(void) { Job item; pthread_t tid1, tid2; int i, err; item = (Job)malloc(sizeof(struct job)); item->next = NULL; item->val = 0; item->tid = -1; if ((err = pthread_create(&tid1, NULL, tfn7, item)) == -1) { printf("fail to create thread %s\n", strerror(err)); exit(0); } if ((err = pthread_create(&tid2, NULL, tfn7, item)) == -1) { printf("fail to create thread %s\n", strerror(err)); exit(0); } printf("==== the 1st put====\n"); pthread_mutex_lock(&q_lock); for(i = 0; i< 2; i++) { if (insert(&item, i, tid1) == -1) { exit(1); } if (insert(&item, i + 1, tid2) == -1) { exit(1); } } if (insert(&item, 10, tid1) == -1) { exit(1); } pthread_mutex_unlock(&q_lock); printf("=== the 2nd put =====\n"); pthread_mutex_lock(&q_lock); if (insert(&item, 9, tid2) == -1) { exit(1); } pthread_mutex_unlock(&q_lock); err = pthread_join(tid1, NULL); if (err != 0) { printf("can't join thread %s\n", strerror(err)); exit(1); } err = pthread_join(tid2, NULL); if (err != 0) { printf("can't join thread %s\n", strerror(err)); exit(1); } printf("main thread done\n"); if (item->next == NULL) { printf("No job in the queue\n"); } free_job(&item); return 0; }
/** SIGCHLD handler **/ void handler(int signum, siginfo_t *info, void *context) { int cpid, status; cpid = info->si_pid; // sending pid //printf("Got a SIGCHLD from %d!\n", cpid); // loop to catch simultaneous SIGCHLDs while( (cpid = waitpid(-1, &status, WNOHANG | WUNTRACED | WCONTINUED)) > 0 ) { //printf("HANDLER Got %d from waitpid\n", cpid); job *j = get_job(job_list, cpid); if(j == NULL) { printf("Error: get_job returned null\n"); _exit(EXIT_FAILURE); } if(WIFEXITED(status)) { // completed if( set_complete(j, cpid) == -1 ) { printf("HANDLER set_complete went awry!\n"); _exit(EXIT_FAILURE); } } else if(WIFSIGNALED(status)) { // terminated set_complete(j, cpid); printf("\n"); //printf("TERMINATED: %d\n", WTERMSIG(status)); } else if(WIFSTOPPED(status)) { // stopped j->running = 0; if(j->fg) { send_back(job_list, j->pgid); printf("\nStopped: %s\n", j->rawcmd); } else { // queue stopped message message *m = malloc(sizeof(message)); copy_to_buf(j->rawcmd, m->msg); m->status = 0; push(msg_q, PROCESS, (void *)m); } } else if(WIFCONTINUED(status)) { // continued j->running = 1; //printf("CONTINUED\n"); } if(j->complete) { j->running = 0; if(!j->fg) { // queue finished message message *m = malloc(sizeof(message)); copy_to_buf(j->rawcmd, m->msg); m->status = 1; push(msg_q, PROCESS, (void *)m); free_job(del_job(job_list, j->pgid)); } } } //printf("HANDLER Done with waitpid loop\n"); }
int job_start(char **argv, void *data, rstream_cb stdout_cb, rstream_cb stderr_cb, job_exit_cb job_exit_cb) { int i; Job *job; // Search for a free slot in the table for (i = 0; i < MAX_RUNNING_JOBS; i++) { if (table[i] == NULL) { break; } } if (i == MAX_RUNNING_JOBS) { // No free slots return 0; } job = xmalloc(sizeof(Job)); // Initialize job->id = i + 1; job->pending_refs = 3; job->pending_closes = 4; job->data = data; job->stdout_cb = stdout_cb; job->stderr_cb = stderr_cb; job->exit_cb = job_exit_cb; job->stopped = false; job->exit_timeout = EXIT_TIMEOUT; job->proc_opts.file = argv[0]; job->proc_opts.args = argv; job->proc_opts.stdio = job->stdio; job->proc_opts.stdio_count = 3; job->proc_opts.flags = UV_PROCESS_WINDOWS_HIDE; job->proc_opts.exit_cb = exit_cb; job->proc_opts.cwd = NULL; job->proc_opts.env = NULL; job->proc.data = NULL; job->proc_stdin.data = NULL; job->proc_stdout.data = NULL; job->proc_stderr.data = NULL; // Initialize the job std{in,out,err} uv_pipe_init(uv_default_loop(), &job->proc_stdin, 0); job->stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; job->stdio[0].data.stream = (uv_stream_t *)&job->proc_stdin; uv_pipe_init(uv_default_loop(), &job->proc_stdout, 0); job->stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; job->stdio[1].data.stream = (uv_stream_t *)&job->proc_stdout; uv_pipe_init(uv_default_loop(), &job->proc_stderr, 0); job->stdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; job->stdio[2].data.stream = (uv_stream_t *)&job->proc_stderr; // Spawn the job if (uv_spawn(uv_default_loop(), &job->proc, &job->proc_opts) != 0) { free_job(job); return -1; } // Give all handles a reference to the job handle_set_job((uv_handle_t *)&job->proc, job); handle_set_job((uv_handle_t *)&job->proc_stdin, job); handle_set_job((uv_handle_t *)&job->proc_stdout, job); handle_set_job((uv_handle_t *)&job->proc_stderr, job); job->in = wstream_new(JOB_WRITE_MAXMEM); wstream_set_stream(job->in, (uv_stream_t *)&job->proc_stdin); // Start the readable streams job->out = rstream_new(read_cb, JOB_BUFFER_SIZE, job, true); job->err = rstream_new(read_cb, JOB_BUFFER_SIZE, job, true); rstream_set_stream(job->out, (uv_stream_t *)&job->proc_stdout); rstream_set_stream(job->err, (uv_stream_t *)&job->proc_stderr); rstream_start(job->out); rstream_start(job->err); // Save the job to the table table[i] = job; // Start polling job status if this is the first if (job_count == 0) { uv_prepare_start(&job_prepare, job_prepare_cb); } job_count++; return job->id; }
int main(int argc, char** argv) { ssize_t cmd_size; int i; int pipefd[2], fin, fout; char buf[BUFFER_SIZE]; char *cmd; char **args; job *j; job_list = init_list(); msg_q = init_list(); pid_t pgid; /* initial setup */ shell_pgid = getpgid(0); sync_pwd(); /* disable (ignore) job control signals */ signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGTSTP, SIG_IGN); signal(SIGINT, SIG_IGN); set_handler(); /*** Shell loop ***/ for(;;) { /* Print out queued messages */ for(i=0;i<msg_q->size;i++) { message *m = (message *) get(msg_q, i); printf("%s: %s\n", m->status ? "Finished" : "Stopped", m->msg); } // clear the queue while(msg_q->size > 0) free(del(msg_q,0)); /* TODO: shell print macro */ printf("%s %s %s ", SHELL, pwd, PROMPT); fflush(stdout); do cmd_size = read(STDIN_FILENO, buf, BUFFER_SIZE); while(cmd_size == -1 && errno == EINTR); // ignore system call interrupts if(cmd_size == -1) { perror("read"); continue; } else if(cmd_size == 0) { // EOF (quit) write(STDOUT_FILENO, EXIT_MSG, STRING_SIZE(EXIT_MSG)); cleanup(); _exit(EXIT_SUCCESS); } else if(cmd_size == 1 && buf[0] == '\n') { continue; } if(buf[cmd_size-1] != '\n') { // overflow write(STDOUT_FILENO, OFLOW_MSG, STRING_SIZE(OFLOW_MSG)); pflush(); continue; } buf[cmd_size-1] = '\0'; // strip the newline j = parse(buf); if(j == (job *) NULL) { printf("Invalid redirections you moron!\n"); continue; } args = j->cmds[0]; if (!my_strcmp(args[0], "fg")) { do_fg(args); free_job(j); continue; } else if (!my_strcmp(args[0], "bg")) { do_bg(args); free_job(j); continue; } else if (!my_strcmp(args[0], "jobs")) { print_bg(job_list); free_job(j); continue; } else if (!my_strcmp(args[0], "cd")) { do_cd(args); free_job(j); continue; } j->job_id = gen_job_id(job_list); j->running = 1; j->complete = 0; push(job_list, JOB, (void *)j); pgid = 0; // set the job pgid to be the first child's pid fin = STDIN_FILENO; for(i=0;i<(j->numcmds);i++) { args = j->cmds[i]; cmd = args[0]; if(i + 1 < (j->numcmds)) { // not last process in job //printf("Creating a pipe!\n"); if(pipe(pipefd) == -1) { perror("pipe"); exit(EXIT_FAILURE); } fout = pipefd[1]; } else fout = STDOUT_FILENO; /*printf("Forking %s\n", cmd); k = 0; while( args[k] != (char *) NULL ) { printf("\targv[%d] = %s\n", k, args[k]); ++k; }*/ pid = fork(); if(pid == -1) { perror("fork"); continue; } /*** CHILD ***/ if(!pid) { // < if(j->fin[i] != (char *) NULL) { if( (fin = open(j->fin[i], O_RDONLY)) == -1 ) { perror("open"); } } // > if(j->fout[i] != (char *) NULL) { if( (fout = open(j->fout[i], O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1 ) { perror("open"); } } exec_process(cmd, args, pgid, fin, fout, j->fg); } /*** PARENT ***/ else { if(!pgid) { // set to first child's pid (process group leader) pgid = pid; j->pgid = pgid; //printf("Set job's pgid to %d\n", pgid); } process *proc = malloc(sizeof(process)); proc->complete = 0; proc->pid = pid; proc->pgid = pgid; push(j->pid_list, PROCESS, (void *)proc); if( setpgid(pid, pgid) == -1 ) { perror("setpgid"); _exit(EXIT_FAILURE); } } if(fin != STDIN_FILENO) close(fin); if(fout != STDOUT_FILENO) close(fout); fin = pipefd[0]; } //print_jobs(); if(j->fg) { // foreground // give terminal control to job if( tcsetpgrp(STDIN_FILENO, pgid) == -1 ) { perror("tcsetpgrp"); _exit(EXIT_FAILURE); } // wait for job to finish jwait(j); // give pmsh terminal control again if( tcsetpgrp(STDIN_FILENO, shell_pgid) == -1 ) { perror("tcsetpgrp"); _exit(EXIT_FAILURE); } } else { // background printf("Running: %s\n", j->rawcmd); } } }