static void cleanup_env(void) { if (g_role == arbiter) { cleanup_arbiter(); } else { cleanup_child(); } }
static void rsn_dec_dispose (GObject * object) { RsnDec *self = (RsnDec *) object; cleanup_child (self); G_OBJECT_CLASS (rsn_dec_parent_class)->dispose (object); }
static GstStateChangeReturn rsn_dec_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; RsnDec *self = RSN_DEC (element); RsnDecClass *klass = RSN_DEC_GET_CLASS (element); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY:{ GstElement *new_child; const GList *decoder_factories; new_child = gst_element_factory_make ("autoconvert", NULL); decoder_factories = klass->get_decoder_factories (klass); g_object_set (G_OBJECT (new_child), "factories", decoder_factories, NULL); if (new_child == NULL || !rsn_dec_set_child (self, new_child)) ret = GST_STATE_CHANGE_FAILURE; break; } case GST_STATE_CHANGE_READY_TO_PAUSED: break; default: break; } if (ret == GST_STATE_CHANGE_FAILURE) return ret; ret = GST_ELEMENT_CLASS (rsn_dec_parent_class)->change_state (element, transition); if (ret == GST_STATE_CHANGE_FAILURE) return ret; switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: break; case GST_STATE_CHANGE_READY_TO_NULL: cleanup_child (self); break; default: break; } return ret; }
int exec_wait() { int i, j; int ret; int fd_max; int pid; int status; int finished; fd_set fds; /* Handle naive make1() which does not know if commands are running. */ if ( !cmdsrunning ) return 0; /* Process children that signaled. */ finished = 0; while ( !finished && cmdsrunning ) { /* Compute max read file descriptor for use in select(). */ populate_file_descriptors( &fd_max, &fds ); if ( 0 < globs.timeout ) { /* Force select() to timeout so we can terminate expired processes. */ tv.tv_sec = select_timeout; tv.tv_nsec = 0; /* select() will wait until: i/o on a descriptor, a signal, or we * time out. */ ret = pselect( fd_max + 1, &fds, 0, 0, &tv, &empty_sigmask ); } else { /* pselect() will wait until i/o on a descriptor or a signal. */ ret = pselect( fd_max + 1, &fds, 0, 0, 0, &empty_sigmask ); } if (-1 == ret && errno != EINTR) { perror("pselect()"); exit(-1); } if (0 < child_events) { /* child terminated via SIGCHLD */ for (i=0; i<MAXJOBS; ++i) { if (0 < terminated_children[i].pid) { pid_t pid = terminated_children[i].pid; /* get index of terminated pid */ for (j=0; j<globs.jobs; ++j) { if (pid == cmdtab[j].pid) { /* cleanup loose ends for terminated process */ close_streams(j, OUT); if ( globs.pipe_action != 0 ) close_streams(j, ERR); cleanup_child(j, terminated_children[i].status); --cmdsrunning; finished = 1; break; } } /* clear entry from list */ terminated_children[i].status = 0; terminated_children[i].pid = 0; --child_events; } } } if ( 0 < ret ) { for ( i = 0; i < globs.jobs; ++i ) { int out = 0; int err = 0; if ( FD_ISSET( cmdtab[ i ].fd[ OUT ], &fds ) ) out = read_descriptor( i, OUT ); if ( ( globs.pipe_action != 0 ) && ( FD_ISSET( cmdtab[ i ].fd[ ERR ], &fds ) ) ) err = read_descriptor( i, ERR ); /* If feof on either descriptor, then we are done. */ if ( out || err ) { /* Close the stream and pipe descriptors. */ close_streams( i, OUT ); if ( globs.pipe_action != 0 ) close_streams( i, ERR ); /* Reap the child and release resources. */ pid = waitpid( cmdtab[ i ].pid, &status, 0 ); if ( pid == cmdtab[ i ].pid ) { /* move into function so signal handler can also use */ finished = 1; cleanup_child(i, status); --cmdsrunning; } else { printf( "unknown pid %d with errno = %d\n", pid, errno ); exit( EXITBAD ); } } } } } return 1; }
/* * child_fn() - Inside container * * XXX (garrcoop): add more calls to cleanup_child()? */ int child_fn(void *arg) { pid_t pid, ppid; struct sigaction sa; struct sigevent notif; char buf[5]; /* Set process id and parent pid */ pid = getpid(); ppid = getppid(); if (pid != CHILD_PID || ppid != PARENT_PID) { printf("pidns was not created\n"); return 1; } /* Close the appropriate end of each pipe */ close(child_to_father[0]); close(father_to_child[1]); while (read(father_to_child[0], buf, 1) != 1) sleep(1); mqd = syscall(__NR_mq_open, mqname, O_RDONLY); if (mqd == -1) { perror("mq_open failed"); return 1; } else printf("mq_open succeeded\n"); /* Register for notification on message arrival */ notif.sigev_notify = SIGEV_SIGNAL; notif.sigev_signo = SIGUSR1; notif.sigev_value.sival_int = mqd; if (syscall(__NR_mq_notify, mqd, ¬if) == -1) { perror("mq_notify failed"); return 1; } else printf("successfully registered for notification\n"); /* Define handler for SIGUSR1 */ sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = child_signal_handler; if (sigaction(SIGUSR1, &sa, NULL) == -1) { perror("sigaction failed"); return 1; } else printf("successfully registered handler for SIGUSR1\n"); /* Ask parent to send a message to the mqueue */ if (write(child_to_father[1], "c:ok", 5) != 5) { perror("write failed"); return 1; } sleep(3); /* Has parent sent a message? */ read(father_to_child[0], buf, 5); if (strcmp(buf, "f:ok") != 0) { printf("parent did not send the message!\n"); return 1; } printf("parent is done - cleaning up\n"); cleanup_child(); exit(0); }
/* * Wait for up to <threshold> seconds for a exec-ed process to finish. * If the process completes the cleanup function is called to cleanup * and the status is returned. * * If the procees did not complete the cleanup function is launched in a new * thread to wait for the process to complete asynchronously and control * is retuned to the caller with a -2 return. * * The cleanup function must continue to wait on the pid and cleanup * after the process exits by closing file descriptors, freeing any * associated memory and calling end_this_activity for the job. * * start_activity must be called prior to calling this function. * * Returns: * 0 process exited successfully, cleanup_child has been called * -1 process exited with an error, cleanup_child has been called * -2 process did not yet complete. The cleanup function has been * called to wait for it. */ int bounded_activity_wait( int *status, int threshold, char *jobid, pid_t pid, void *cl_args, void * (*cleanup_child)(void *)) { /* variables to control the transition to asynchronous */ int total_wait = 0; int ret_val = 0; pthread_t tid; timespec_t waitspec = {1, 0}; Trace(TR_DEBUG, "about to enter wait for process %ld", pid); if (ISNULL(status, jobid, cl_args, cleanup_child)) { Trace(TR_ERR, "bounded wait err: %d %s", samerrno, samerrmsg); return (-1); } /* * wait for the process without hanging and leave it as you * found it so the cleanup function can handle its completion * error as it sees fit. */ for (;;) { ret_val = waitpid(pid, status, WNOHANG | WNOWAIT); if (ret_val == -1 && errno != EINTR) { /* waitpid hit an error */ break; } else if (ret_val == pid) { /* the process is done */ break; } nanosleep(&waitspec, NULL); total_wait += 1; if (total_wait >= threshold) { Trace(TR_MISC, "going asynch for %s(%ld)", Str(jobid), pid); /* go asynchronous */ pthread_create(&tid, &samr_pth_attr, cleanup_child, cl_args); set_pid_or_tid(jobid, 0, tid); return (-2); } } /* the process either exited (error or success) or waitpid failed */ /* call the cleanup function in this thread */ cleanup_child(cl_args); if (ret_val < 0 || !WIFEXITED(*status) || WEXITSTATUS(*status)) { /* * wait failed OR process abnormally terminated OR * process exited with non zero exit code */ return (-1); } else { return (0); } }