FreeBSD/sys/kern/kern_event.c
/*
 * Called when the process forked. It mostly does the same as the
 * knote(), activating all knotes registered to be activated when the
 * process forked. Additionally, for each knote attached to the
 * parent, check whether user wants to track the new process. If so
 * attach a new knote to it, and immediately report an event with the
 * child's pid.
 */
Called when the process forked. It mostly does the same as the
knote(), activating all knotes registered to be activated when the
process forked. Additionally, for each knote attached to the
parent, check whether user wants to track the new process. If so
attach a new knote to it, and immediately report an event with the
child's pid.
Called when the process forked . It mostly does the same as the knote () activating all knotes registered to be activated when the process forked . Additionally for each knote attached to the parent check whether user wants to track the new process . If so attach a new knote to it and immediately report an event with the child ' s pid .
void
knote_fork(struct knlist *list, int pid)
{
	struct kqueue *kq;
	struct knote *kn;
	struct kevent kev;
	int error;
	if (list == NULL)
		return;
	list->kl_lock(list->kl_lockarg);
	SLIST_FOREACH(kn, &list->kl_list, kn_selnext) {
		kq = kn->kn_kq;
		KQ_LOCK(kq);
		if ((kn->kn_status & (KN_INFLUX | KN_SCAN)) == KN_INFLUX) {
			KQ_UNLOCK(kq);
			continue;
		}
		if ((kn->kn_sfflags & NOTE_TRACK) == 0) {
			kn->kn_status |= KN_HASKQLOCK;
			if (kn->kn_fop->f_event(kn, NOTE_FORK))
				KNOTE_ACTIVATE(kn, 1);
			kn->kn_status &= ~KN_HASKQLOCK;
			KQ_UNLOCK(kq);
			continue;
		}
		kn->kn_status |= KN_INFLUX;
		KQ_UNLOCK(kq);
		list->kl_unlock(list->kl_lockarg);
		kev.ident = pid;
		kev.filter = kn->kn_filter;
		kev.flags = kn->kn_flags | EV_ADD | EV_ENABLE | EV_ONESHOT |
		    EV_FLAG2;
		kev.fflags = kn->kn_sfflags;
		kev.data = kn->kn_id;		
		kev.udata = kn->kn_kevent.udata;
		error = kqueue_register(kq, &kev, NULL, 0);
		if (error)
			kn->kn_fflags |= NOTE_TRACKERR;
		kev.ident = pid;
		kev.filter = kn->kn_filter;
		kev.flags = kn->kn_flags | EV_ADD | EV_ENABLE | EV_FLAG1;
		kev.fflags = kn->kn_sfflags;
		kev.data = kn->kn_id;		
		kev.udata = kn->kn_kevent.udata;
		error = kqueue_register(kq, &kev, NULL, 0);
		if (error)
			kn->kn_fflags |= NOTE_TRACKERR;
		if (kn->kn_fop->f_event(kn, NOTE_FORK))
			KNOTE_ACTIVATE(kn, 0);
		KQ_LOCK(kq);
		kn->kn_status &= ~KN_INFLUX;
		KQ_UNLOCK_FLUX(kq);
		list->kl_lock(list->kl_lockarg);
	}
	list->kl_unlock(list->kl_lockarg);
}
void knote_fork ( struct knlist * list , int pid ) { struct kqueue * kq ; struct knote * kn ; struct kevent kev ; int error ; if ( list == NULL ) return ; list -> kl_lock ( list -> kl_lockarg ) ; SLIST_FOREACH ( kn , & list -> kl_list , kn_selnext ) { kq = kn -> kn_kq ; KQ_LOCK ( kq ) ; if ( ( kn -> kn_status & ( KN_INFLUX | KN_SCAN ) ) == KN_INFLUX ) { KQ_UNLOCK ( kq ) ; continue ; } if ( ( kn -> kn_sfflags & NOTE_TRACK ) == 0 ) { kn -> kn_status |= KN_HASKQLOCK ; if ( kn -> kn_fop -> f_event ( kn , NOTE_FORK ) ) KNOTE_ACTIVATE ( kn , 1 ) ; kn -> kn_status &= ~ KN_HASKQLOCK ; KQ_UNLOCK ( kq ) ; continue ; } kn -> kn_status |= KN_INFLUX ; KQ_UNLOCK ( kq ) ; list -> kl_unlock ( list -> kl_lockarg ) ; kev . ident = pid ; kev . filter = kn -> kn_filter ; kev . flags = kn -> kn_flags | EV_ADD | EV_ENABLE | EV_ONESHOT | EV_FLAG2 ; kev . fflags = kn -> kn_sfflags ; kev . data = kn -> kn_id ; kev . udata = kn -> kn_kevent . udata ; error = kqueue_register ( kq , & kev , NULL , 0 ) ; if ( error ) kn -> kn_fflags |= NOTE_TRACKERR ; kev . ident = pid ; kev . filter = kn -> kn_filter ; kev . flags = kn -> kn_flags | EV_ADD | EV_ENABLE | EV_FLAG1 ; kev . fflags = kn -> kn_sfflags ; kev . data = kn -> kn_id ; kev . udata = kn -> kn_kevent . udata ; error = kqueue_register ( kq , & kev , NULL , 0 ) ; if ( error ) kn -> kn_fflags |= NOTE_TRACKERR ; if ( kn -> kn_fop -> f_event ( kn , NOTE_FORK ) ) KNOTE_ACTIVATE ( kn , 0 ) ; KQ_LOCK ( kq ) ; kn -> kn_status &= ~ KN_INFLUX ; KQ_UNLOCK_FLUX ( kq ) ; list -> kl_lock ( list -> kl_lockarg ) ; } list -> kl_unlock ( list -> kl_lockarg ) ; }
Called when the process forked.
Called when the process forked .
/*
		 * The same as knote(), activate the event.
		 */ /*
		 * The NOTE_TRACK case. In addition to the activation
		 * of the event, we need to register new events to
		 * track the child. Drop the locks in preparation for
		 * the call to kqueue_register().
		 */ /*
		 * Activate existing knote and register tracking knotes with
		 * new process.
		 *
		 * First register a knote to get just the child notice. This
		 * must be a separate note from a potential NOTE_EXIT
		 * notification since both NOTE_CHILD and NOTE_EXIT are defined
		 * to use the data field (in conflicting ways).
		 */ /* parent */ /* preserve udata */ /*
		 * Then register another knote to track other potential events
		 * from the new process.
		 */ /* parent */ /* preserve udata */