On Thu, 2008-06-12 at 14:24 +0530, Subrata Modak wrote:
> Thanks for this. I will test and get back to you soon.
> 
> Regards--
> Subrata
> 
> On Thu, 2008-06-12 at 14:18 +0800, Li Zefan wrote:
> > Process event connector is a netlink connector that reports process
> > events to userspace, and currently we have 5 kinds of process events,
> > i.e. fork, exit, exec, uid, gid.
> > 
> > There are total 5 test cases to test its functionality.
> > 
> > But the test is not run by default, because I don't find a way to
> > decide whether the underlying kernel supports this feather or not.
> > 
> > Signed-off-by: Li Zefan <[EMAIL PROTECTED]>
> > ---
> >  runtest/connectors                                |    2
> >  testcases/kernel/connectors/Makefile              |   10
> >  testcases/kernel/connectors/pec/Makefile          |   13
> >  testcases/kernel/connectors/pec/README            |   46 +++
> >  testcases/kernel/connectors/pec/event_generator.c |  227 ++++++++++++++++
> >  testcases/kernel/connectors/pec/pec_listener.c    |  309 
> > ++++++++++++++++++++++
> >  testcases/kernel/connectors/pec/run_pec_test      |   92 ++++++
> >  7 files changed, 699 insertions(+)
> > 
> > diff -Nurp ltp-full-20080531.orig/runtest/connectors 
> > ltp-full-20080531/runtest/connectors
> > --- ltp-full-20080531.orig/runtest/connectors       1970-01-01 
> > 08:00:00.000000000 +0800
> > +++ ltp-full-20080531/runtest/connectors    2008-06-12 13:46:44.000000000 
> > +0800
> > @@ -0,0 +1,2 @@
> > +#DESCRIPTION:Netlink Connector tests
> > +Connectors run_pec_test
> > diff -Nurp ltp-full-20080531.orig/testcases/kernel/connectors/Makefile 
> > ltp-full-20080531/testcases/kernel/connectors/Makefile
> > --- ltp-full-20080531.orig/testcases/kernel/connectors/Makefile     
> > 1970-01-01 08:00:00.000000000 +0800
> > +++ ltp-full-20080531/testcases/kernel/connectors/Makefile  2008-05-21 
> > 09:50:24.000000000 +0800
> > @@ -0,0 +1,10 @@
> > +SUBDIRS = pec
> > +
> > +all:
> > +   @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i ; done
> > +
> > +install:
> > +   @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i install ; done
> > +
> > +clean:
> > +   @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i clean ; done
> > diff -Nurp 
> > ltp-full-20080531.orig/testcases/kernel/connectors/pec/event_generator.c 
> > ltp-full-20080531/testcases/kernel/connectors/pec/event_generator.c
> > --- 
> > ltp-full-20080531.orig/testcases/kernel/connectors/pec/event_generator.c    
> >     1970-01-01 08:00:00.000000000 +0800
> > +++ ltp-full-20080531/testcases/kernel/connectors/pec/event_generator.c     
> > 2008-05-21 10:48:09.000000000 +0800
> > @@ -0,0 +1,227 @@
> > +/******************************************************************************/
> > +/*                                                                         
> >    */
> > +/* Copyright (c) 2008 FUJITSU LIMITED                                      
> >    */
> > +/*                                                                         
> >    */
> > +/* This program is free software;  you can redistribute it and/or modify   
> >    */
> > +/* it under the terms of the GNU General Public License as published by    
> >    */
> > +/* the Free Software Foundation; either version 2 of the License, or       
> >    */
> > +/* (at your option) any later version.                                     
> >    */
> > +/*                                                                         
> >    */
> > +/* This program is distributed in the hope that it will be useful,         
> >    */
> > +/* but WITHOUT ANY WARRANTY;  without even the implied warranty of         
> >    */
> > +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See               
> >    */
> > +/* the GNU General Public License for more details.                        
> >    */
> > +/*                                                                         
> >    */
> > +/* You should have received a copy of the GNU General Public License       
> >    */
> > +/* along with this program;  if not, write to the Free Software            
> >    */
> > +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
> >    */
> > +/*                                                                         
> >    */
> > +/* Author: Li Zefan <[EMAIL PROTECTED]>                                    
> >  */
> > +/*                                                                         
> >    */
> > +/******************************************************************************/
> > +
> > +#include <unistd.h>
> > +#include <string.h>
> > +#include <stdlib.h>
> > +#include <stdio.h>
> > +#include <pwd.h>
> > +#include "test.h"
> > +
> > +#define DEFAULT_EVENT_NUM       1
> > +
> > +unsigned long nr_event = DEFAULT_EVENT_NUM;
> > +
> > +uid_t ltp_uid;
> > +gid_t ltp_gid;
> > +const char *ltp_user = "nobody";
> > +
> > +char **exec_argv;
> > +
> > +void (*gen_event)(void);
> > +
> > +/*
> > + * Show the usage
> > + *
> > + * @status: the exit status
> > + */
> > +static void usage(int status)
> > +{
> > +   FILE *stream = (status ? stderr : stdout);
> > +
> > +   fprintf(stream, "Usage: event_generator -e fork|exit|exec|uid|gid [-n 
> > nr_event]\n");
> > +
> > +   exit(status);
> > +}
> > +
> > +/*
> > + * Generate exec event.
> > + *
> > + * We can't just exec nr_event times, because the current process image
> > + * will be replaced with the new process image, so we use enviroment
> > + * viriable as event counters, as it will be inherited after exec.
> > + */
> > +static void gen_exec(void)
> > +{
> > +   char *val;
> > +   char buf[10];
> > +   unsigned long nr_exec;
> > +
> > +   /* get the event counter */
> > +   val = getenv("NR_EXEC");
> > +   if (!val) {
> > +           nr_exec = 0;
> > +           setenv("NR_EXEC", "1", 1);
> > +   } else {
> > +           nr_exec = atoi(val);
> > +           snprintf(buf, 10, "%lu", nr_exec + 1);
> > +           setenv("NR_EXEC", buf, 1);
> > +   }
> > +
> > +   /* stop generate exec event */
> > +   if (nr_exec >= nr_event)
> > +           return;
> > +
> > +   /* fflush is needed before exec */
> > +   printf("exec pid: %d\n", getpid());
> > +   fflush(stdout);
> > +
> > +   execv(exec_argv[0], exec_argv);
> > +}
> > +
> > +/*
> > + * Generate fork event.
> > + */
> > +static inline void gen_fork(void)
> > +{
> > +   pid_t pid;
> > +
> > +   pid = fork();
> > +   if (pid == 0) {
> > +           printf("fork parent: %d, child: %d\n", getppid(), getpid());
> > +           exit(0);
> > +   } else if (pid < 0) {
> > +           fprintf(stderr, "fork() failed\n");
> > +           exit(1);
> > +   }
> > +}
> > +
> > +/**
> > + * Generate exit event
> > + */
> > +static inline void gen_exit(void)
> > +{
> > +   pid_t pid;
> > +
> > +   pid = fork();
> > +   if (pid == 0) {
> > +           printf("exit pid: %d exit_code: %d\n", getpid(), 0);
> > +           exit(0);
> > +   } else if (pid < 0){
> > +           fprintf(stderr, "fork() failed\n");
> > +           exit(1);
> > +   }
> > +}
> > +
> > +/*
> > + * Generate uid event.
> > + */
> > +static inline void gen_uid(void)
> > +{
> > +   setuid(ltp_uid);
> > +   printf("uid pid: %d euid: %d\n", getpid(), ltp_uid);
> > +}
> > +
> > +/*
> > + * Generate gid event.
> > + */
> > +static inline void gen_gid(void)
> > +{
> > +   setgid(ltp_gid);
> > +   printf("gid pid: %d egid: %d\n", getpid(), ltp_gid);
> > +}
> > +
> > +/*
> > + * Read option from user input.
> > + *
> > + * @argc: number of arguments
> > + * @argv: argument list
> > + */
> > +static void process_options(int argc, char **argv)
> > +{
> > +   char c;
> > +   char *end;
> > +
> > +   while ((c = getopt(argc, argv, "e:n:h")) != -1) {
> > +           switch (c) {
> > +           /* which event to generate */
> > +           case 'e':
> > +                   if (!strcmp(optarg, "exec"))
> > +                           gen_event = gen_exec;
> > +                   else if (!strcmp(optarg, "fork"))
> > +                           gen_event = gen_fork;
> > +                   else if (!strcmp(optarg, "exit"))
> > +                           gen_event = gen_exit;
> > +                   else if (!strcmp(optarg, "uid"))
> > +                           gen_event = gen_uid;
> > +                   else if (!strcmp(optarg, "gid"))
> > +                           gen_event = gen_gid;
> > +                   else {
> > +                           fprintf(stderr, "wrong -e argument!");
> > +                           exit(1);
> > +                   }
> > +                   break;
> > +           /* number of event to generate */
> > +           case 'n':
> > +                   nr_event = strtoul(optarg, &end, 10);
> > +                   if (*end != '\0' || nr_event == 0) {
> > +                           fprintf(stderr, "wrong -n argument!");
> > +                           exit(1);
> > +                   }
> > +                   break;
> > +           /* help */
> > +           case 'h':
> > +                   usage(0);
> > +           default:
> > +                   fprintf(stderr, "unknown option!\n");
> > +                   usage(1);
> > +           }
> > +   }
> > +
> > +   if (!gen_event) {
> > +           fprintf(stderr, "no event type specified!\n");
> > +           usage(1);
> > +   }
> > +}
> > +
> > +int main(int argc, char **argv)
> > +{
> > +   unsigned long i;
> > +   struct passwd *ent;
> > +
> > +   process_options(argc, argv);
> > +
> > +   ent = getpwnam(ltp_user);
> > +   if (ent == NULL) {
> > +           fprintf(stderr, "can't get password entry for %s", ltp_user);
> > +           exit(1);
> > +   }
> > +   ltp_uid = ent->pw_uid;
> > +   ltp_gid = ent->pw_gid;
> > +

Since you don't wait for fork()'d child processes how about a:
        signal(SIGCHLD, SIG_IGN);

Which will prevent them from ever becoming zombies.

> > +   /* special processing for gen_exec, see comments above gen_exec() */
> > +   if (gen_event == gen_exec) {
> > +           exec_argv = argv;
> > +
> > +           gen_exec();
> > +
> > +           /* won't reach here */
> > +           return 0;
> > +   }
> > +
> > +   /* other events */
> > +   for (i = 0; i < nr_event; i++)
> > +           gen_event();
> > +
> > +   return 0;
> > +}
> > +
> > diff -Nurp ltp-full-20080531.orig/testcases/kernel/connectors/pec/Makefile 
> > ltp-full-20080531/testcases/kernel/connectors/pec/Makefile
> > --- ltp-full-20080531.orig/testcases/kernel/connectors/pec/Makefile 
> > 1970-01-01 08:00:00.000000000 +0800
> > +++ ltp-full-20080531/testcases/kernel/connectors/pec/Makefile      
> > 2008-05-20 10:33:55.000000000 +0800
> > @@ -0,0 +1,13 @@
> > +CFLAGS +=       -I../../../../include -Wall
> > +LOADLIBES+=     -L../../../../lib -lltp
> > +
> > +SRCS:=$(wildcard *.c)
> > +TARGETS:=$(patsubst %.c,%,$(SRCS))
> > +
> > +all: $(TARGETS)
> > + 
> > +install:
> > +   @set -e; for i in $(TARGETS) ; do ln -f $$i ../../../bin/$$i ; chmod +x 
> > run_pec_test ; done ;
> > +   ln -f run_pec_test ../../../bin/
> > +clean:
> > +   rm -f $(TARGETS)
> > diff -Nurp 
> > ltp-full-20080531.orig/testcases/kernel/connectors/pec/pec_listener.c 
> > ltp-full-20080531/testcases/kernel/connectors/pec/pec_listener.c
> > --- ltp-full-20080531.orig/testcases/kernel/connectors/pec/pec_listener.c   
> > 1970-01-01 08:00:00.000000000 +0800
> > +++ ltp-full-20080531/testcases/kernel/connectors/pec/pec_listener.c        
> > 2008-05-21 10:48:01.000000000 +0800
> > @@ -0,0 +1,309 @@
> > +/******************************************************************************/
> > +/*                                                                         
> >    */
> > +/* Copyright (c) 2008 FUJITSU LIMITED                                      
> >    */
> > +/*                                                                         
> >    */
> > +/* This program is free software;  you can redistribute it and/or modify   
> >    */
> > +/* it under the terms of the GNU General Public License as published by    
> >    */
> > +/* the Free Software Foundation; either version 2 of the License, or       
> >    */
> > +/* (at your option) any later version.                                     
> >    */
> > +/*                                                                         
> >    */
> > +/* This program is distributed in the hope that it will be useful,         
> >    */
> > +/* but WITHOUT ANY WARRANTY;  without even the implied warranty of         
> >    */
> > +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See               
> >    */
> > +/* the GNU General Public License for more details.                        
> >    */
> > +/*                                                                         
> >    */
> > +/* You should have received a copy of the GNU General Public License       
> >    */
> > +/* along with this program;  if not, write to the Free Software            
> >    */
> > +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
> >    */
> > +/*                                                                         
> >    */
> > +/* Author: Li Zefan <[EMAIL PROTECTED]>                                    
> >  */
> > +/*                                                                         
> >    */
> > +/******************************************************************************/
> > +
> > +#include <unistd.h>
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <string.h>
> > +#include <errno.h>
> > +#include <signal.h>
> > +#include <sys/socket.h>
> > +#include <sys/poll.h>
> > +
> > +#include <linux/netlink.h>
> > +#include <linux/connector.h>
> > +#include <linux/cn_proc.h>
> > +
> > +#define PEC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event))
> > +#define PEC_CTRL_MSG_SIZE (sizeof(struct cn_msg) + sizeof(enum 
> > proc_cn_mcast_op))
> > +
> > +#define MAX_MSG_SIZE 256
> > +
> > +static __u32 seq;
> > +
> > +static int exit_flag;
> > +static struct sigaction sigint_action;
> > +
> > +/*
> > + * Handler for signal int. Set exit flag.
> > + *
> > + * @signo: the signal number, not used
> > + */
> > +static void sigint_handler(int __attribute__((unused)) signo)
> > +{
> > +   exit_flag = 1;
> > +}
> > +
> > +/*
> > + * Send netlink package.
> > + *
> > + * @sd: socket descripor
> > + * @to: the destination sockaddr
> > + * @cnmsg: the pec control message
> > + */
> > +static int netlink_send(int sd, struct sockaddr_nl *to, struct cn_msg 
> > *cnmsg)
> > +{
> > +   int ret;
> > +   char buf[MAX_MSG_SIZE];
> > +   struct nlmsghdr *nlhdr;
> > +   struct iovec iov;
> > +   struct msghdr msg;
> > +
> > +   memset(buf, 0, MAX_MSG_SIZE);
> > +
> > +   nlhdr = (struct nlmsghdr *)buf;
> > +
> > +   nlhdr->nlmsg_seq = seq++;
> > +   nlhdr->nlmsg_pid = getpid();
> > +   nlhdr->nlmsg_type = NLMSG_DONE;
> > +   nlhdr->nlmsg_len = NLMSG_LENGTH(sizeof(*cnmsg) + cnmsg->len);
> > +   nlhdr->nlmsg_flags = 0;
> > +   memcpy(NLMSG_DATA(nlhdr), cnmsg, sizeof(*cnmsg) + cnmsg->len);
> > +
> > +   memset(&iov, 0, sizeof(struct iovec));
> > +   iov.iov_base = (void *)nlhdr;
> > +   iov.iov_len = nlhdr->nlmsg_len;
> > +
> > +   memset(&msg, 0, sizeof(struct msghdr));
> > +   msg.msg_name = (void *)to;
> > +   msg.msg_namelen = sizeof(*to);
> > +   msg.msg_iov = &iov;
> > +   msg.msg_iovlen = 1;
> > +
> > +   ret = sendmsg(sd, &msg, 0);
> > +
> > +   return ret;
> > +}
> > +
> > +/*
> > + * Receive package from netlink.
> > + *
> > + * @sd: socket descripor
> > + * @from: source sockaddr
> > + * @buf: buffer for storing the package
> > + */
> > +static int netlink_recv(int sd, struct sockaddr_nl *from, char *buf)
> > +{
> > +   int ret;
> > +   struct nlmsghdr *nlhdr = (struct nlmsghdr *)buf;
> > +   struct iovec iov;
> > +   struct msghdr msg;
> > +
> > +   memset(nlhdr, 0, NLMSG_SPACE(MAX_MSG_SIZE));
> > +   memset(&iov, 0, sizeof(iov));
> > +   memset(&msg, 0, sizeof(msg));
> > +
> > +   iov.iov_base = (void *)nlhdr;
> > +   iov.iov_len = NLMSG_SPACE(MAX_MSG_SIZE);
> > +
> > +   msg.msg_name = (void *)from;
> > +   msg.msg_namelen = sizeof(*from);
> > +   msg.msg_iov = &iov;
> > +   msg.msg_iovlen = 1;
> > +
> > +   ret = recvmsg(sd, &msg, 0);
> > +
> > +   return ret;
> > +}
> > +
> > +/*
> > + * Send control message to PEC.
> > + *
> > + * @sd: socket descriptor
> > + * @to: the destination sockaddr
> > + * @op: control flag
> > + */
> > +static int control_pec(int sd, struct sockaddr_nl *to, enum 
> > proc_cn_mcast_op op)
> > +{
> > +   int ret;
> > +   char buf[PEC_CTRL_MSG_SIZE];
> > +   struct cn_msg *cnmsg;
> > +   enum proc_cn_mcast_op *pec_op;
> > +
> > +   memset(buf, 0, sizeof(buf));
> > +
> > +   cnmsg = (struct cn_msg *)buf;
> > +   cnmsg->id.idx = CN_IDX_PROC;
> > +   cnmsg->id.val = CN_VAL_PROC;
> > +   cnmsg->seq = seq++;
> > +   cnmsg->ack = 0;
> > +   cnmsg->len = sizeof(op);
> > +
> > +   pec_op = (enum proc_cn_mcast_op *)cnmsg->data;
> > +   *pec_op = op;
> > +
> > +   ret = netlink_send(sd, to, cnmsg);
> > +
> > +   return ret;
> > +}
> > +
> > +/*
> > + * Process PEC event.
> > + *
> > + * @nlhdr: the netlinke pacakge
> > + */
> > +static void process_event(struct nlmsghdr *nlhdr)
> > +{
> > +   struct cn_msg *msg;
> > +   struct proc_event *pe;
> > +
> > +   msg = (struct cn_msg *)NLMSG_DATA(nlhdr);
> > +
> > +   pe = (struct proc_event *)msg->data;
> > +
> > +   switch (pe->what) {
> > +   case PROC_EVENT_NONE:
> > +           printf("none err: %u\n", pe->event_data.ack.err);
> > +           break;
> > +   case PROC_EVENT_FORK:
> > +           printf("fork parent: %d, child: %d\n",
> > +                  pe->event_data.fork.parent_pid,
> > +                  pe->event_data.fork.child_pid);
> > +           break;
> > +   case PROC_EVENT_EXEC:
> > +           printf("exec pid: %d\n",
> > +                  pe->event_data.exec.process_pid);
> > +           break;
> > +   case PROC_EVENT_UID:
> > +           printf("uid pid: %d euid: %d ruid: %d\n",
> > +                  pe->event_data.id.process_pid,
> > +                  pe->event_data.id.e.euid,
> > +                  pe->event_data.id.r.ruid);
> > +           break;
> > +   case PROC_EVENT_GID:
> > +           printf("gid pid: %d egid: %d rgid: %d\n",
> > +                  pe->event_data.id.process_pid,
> > +                  pe->event_data.id.e.egid,
> > +                  pe->event_data.id.r.rgid);
> > +           break;
> > +   case PROC_EVENT_EXIT:
> > +           printf("exit pid: %d exit_code: %d exit_signal: %d\n",
> > +                  pe->event_data.exit.process_pid,
> > +                  pe->event_data.exit.exit_code,
> > +                  pe->event_data.exit.exit_signal);
> > +           break;
> > +   default:
> > +           printf("unknown event\n");
> > +           break;
> > +   }
> > +}
> > +
> > +int main(int argc, char **argv)
> > +{
> > +   int ret;
> > +   int sd;
> > +   struct sockaddr_nl l_local;
> > +   struct sockaddr_nl src_addr;
> > +   char buf[MAX_MSG_SIZE];
> > +   struct pollfd pfd;
> > +
> > +   sigint_action.sa_flags = SA_ONESHOT;
> > +   sigint_action.sa_handler = &sigint_handler;
> > +   sigaction(SIGINT, &sigint_action, NULL);
> > +
> > +   /* Create and bind socket */
> > +   sd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
> > +   if (sd == -1) {
> > +           fprintf(stderr, "failed to create socket\n");
> > +           exit(1);
> > +   }
> > +
> > +   memset(&src_addr, 0, sizeof(src_addr));
> > +   src_addr.nl_family = AF_NETLINK;
> > +   src_addr.nl_pid = 0;
> > +   src_addr.nl_groups = 0;
> > +
> > +   memset(&l_local, 0, sizeof(l_local));
> > +   l_local.nl_family = AF_NETLINK;
> > +   l_local.nl_pid = getpid();
> > +   l_local.nl_groups = CN_IDX_PROC;
> > +
> > +   ret = bind(sd, (struct sockaddr *)&l_local,
> > +              sizeof(struct sockaddr_nl));
> > +   if (ret == -1) {
> > +           fprintf(stderr, "failed to bind socket\n");
> > +           exit(1);
> > +   }
> > +
> > +   /* Open PEC listening */
> > +   ret = control_pec(sd, &src_addr, PROC_CN_MCAST_LISTEN);
> > +   if (!ret) {
> > +           fprintf(stderr, "failed to open PEC listening\n");
> > +           exit(1);
> > +   }
> > +
> > +   /* Receive msg from PEC */
> > +   pfd.fd = sd;
> > +   pfd.events = POLLIN;
> > +   pfd.revents = 0;
> > +   while (!exit_flag) {
> > +           struct nlmsghdr *nlhdr;
> > +
> > +           ret = poll(&pfd, 1, -1);
> > +           if (ret == 0 || (ret == -1 && errno != EINTR)) {
> > +                   control_pec(sd, &src_addr, PROC_CN_MCAST_IGNORE);
> > +                   fprintf(stderr, "failed to poll\n");
> > +                   exit(1);
> > +           } else if (ret == -1 && errno == EINTR)
> > +                   break;
> > +
> > +           ret = netlink_recv(sd, &src_addr, buf);
> > +
> > +           if (ret == 0)
> > +                   break;
> > +           else if (ret == -1 && errno == EINTR)
> > +                   break;
> > +           else if (ret == -1 && errno != EINTR) {
> > +                   control_pec(sd, &src_addr, PROC_CN_MCAST_IGNORE);
> > +                   fprintf(stderr, "failed to receive from netlink\n");
> > +                   exit(1);
> > +           } else {
> > +                   nlhdr = (struct nlmsghdr *)buf;
> > +
> > +                   switch (nlhdr->nlmsg_type) {
> > +                   case NLMSG_ERROR:
> > +                           fprintf(stderr, "err message recieved.\n");
> > +                           exit(1);
> > +                           break;
> > +                   case NLMSG_DONE:
> > +                           /* message sent from kernel */
> > +                           if (nlhdr->nlmsg_pid == 0)
> > +                                   process_event(nlhdr);
> > +                           break;
> > +                   default:
> > +                           break;
> > +                   }
> > +           }
> > +   }
> > +
> > +   /* Close PEC listening */
> > +   ret = control_pec(sd, &src_addr, PROC_CN_MCAST_IGNORE);
> > +   if (!ret) {
> > +           fprintf(stderr, "failed to close PEC listening\n");
> > +           exit(1);
> > +   }
> > +
> > +   close(sd);
> > +

I think you should also flush stdout:

        while (fsync(0) == -1) {
                if (errno != EIO)
                        break;
                sleep(10); /* retry once every 10 seconds */
        }

Otherwise you've no guarantee that stdout buffers have been flushed
before the kill (more below). The close() man page has an ominous NOTES
section which I think suggests what could go wrong.

> > +   return 0;
> > +}
> > +
> > diff -Nurp ltp-full-20080531.orig/testcases/kernel/connectors/pec/README 
> > ltp-full-20080531/testcases/kernel/connectors/pec/README
> > --- ltp-full-20080531.orig/testcases/kernel/connectors/pec/README   
> > 1970-01-01 08:00:00.000000000 +0800
> > +++ ltp-full-20080531/testcases/kernel/connectors/pec/README        
> > 2008-05-20 10:07:44.000000000 +0800
> > @@ -0,0 +1,46 @@
> > +
> > +TEST SUITE:
> > +
> > +The directory pec contains the tests related to the process event 
> > connector.
> > +
> > +Process event connector is a netlink connector that reports process events
> > +to userspace. It sends events such as fork, exec, id change and exit.
> > +
> > +There are total 5 testcases.
> > +
> > +TESTS AIM:
> > +
> > +The aim of the tests is to test the functionality of process event 
> > connector.
> > +
> > +FILES DESCRIPTION:
> > +
> > +check_connector_enabled.c
> > +------------------
> > +This program is used to check if the kernel supports netlink connector.
> > +
> > +event_generator.c
> > +------------------
> > +This program is used to generate a specified process event (fork, exec, 
> > uid,
> > +gid or exit).
> > +
> > +run_pec_test
> > +------------------
> > +This script runs all the 5 testcases.
> > +
> > +pec_listener.c
> > +------------------
> > +This program is used to ilsten to process events received through the 
> > kernel
> > +connector and print them.
> > +
> > +Makefile
> > +------------------
> > +The usual makefile for this directory
> > +
> > +$LTPROOT/output/pec/*.log
> > +------------------
> > +The outputs of event_generator and pec_listeners.
> > +
> > +README:
> > +------------------
> > +The one you have gone through.
> > +
> > diff -Nurp 
> > ltp-full-20080531.orig/testcases/kernel/connectors/pec/run_pec_test 
> > ltp-full-20080531/testcases/kernel/connectors/pec/run_pec_test
> > --- ltp-full-20080531.orig/testcases/kernel/connectors/pec/run_pec_test     
> > 1970-01-01 08:00:00.000000000 +0800
> > +++ ltp-full-20080531/testcases/kernel/connectors/pec/run_pec_test  
> > 2008-06-12 13:42:07.000000000 +0800
> > @@ -0,0 +1,92 @@
> > +#! /bin/bash
> > +
> > +################################################################################
> > +##                                                                         
> >    ##
> > +## Copyright (c) 2008 FUJITSU LIMITED                                      
> >    ##
> > +##                                                                         
> >    ##
> > +## This program is free software;  you can redistribute it and#or modify   
> >    ##
> > +## it under the terms of the GNU General Public License as published by    
> >    ##
> > +## the Free Software Foundation; either version 2 of the License, or       
> >    ##
> > +## (at your option) any later version.                                     
> >    ##
> > +##                                                                         
> >    ##
> > +## This program is distributed in the hope that it will be useful, but     
> >    ##
> > +## WITHOUT ANY WARRANTY; without even the implied warranty of 
> > MERCHANTABILITY ##
> > +## or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public 
> > License   ##
> > +## for more details.                                                       
> >    ##
> > +##                                                                         
> >    ##
> > +## You should have received a copy of the GNU General Public License       
> >    ##
> > +## along with this program;  if not, write to the Free Software            
> >    ##
> > +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
> >    ##
> > +##                                                                         
> >    ##
> > +## Author: Li Zefan <[EMAIL PROTECTED]>                                    
> >  ##
> > +##                                                                         
> >    ##
> > +################################################################################
> > +
> > +if [ -z $LTPROOT ]; then
> > +   LTPROOT="`cd ../../../.. && pwd`"
> > +   PATH="$PATH:$LTPROOT/testcases/bin"
> > +   mkdir $LTPROOT/output 2> /dev/null
> > +fi
> > +
> > +cd $LTPROOT/testcases/bin
> > +
> > +export TCID="pec01"
> > +export TST_TOTAL=5
> > +
> > +exit_status=0
> > +
> > +# Run a test case
> > +#
> > +# $1: the test number
> > +# $2: type of event
> > +run_case()
> > +{
> > +   export TST_COUNT=$1
> > +
> > +   log="$LTPROOT/output/log"
> > +   mkdir $log 2> /dev/null
> > +
> > +   ./pec_listener > "$log/listener_$1.log" 2>&1 &
> > +   pid=$!
> > +   sleep 1

You might add comments for these sleeps. I guess this one should be
something like:
        
        # Wait for pec_listener to start listening

> > +
> > +   ./event_generator -e $2 > "$log/generator_$1.log" &
> > +
> > +   wait $!

What does running in the background and then waiting on the
event_generator ($!) process buy us? Couldn't you just do:

        ./event_generator -e $2 > "$log/generator_$1.log"

> > +   ret1=$?
> > +
> > +   sleep 1

The comment for the above sleep might read:
        
        # Sleep until pec_listener has seen and handled all of the generated 
events

Also, in theory ./event_generator could someday generate multiple events
(-n <NUM>). Perhaps there ought to be:

NUM_EVENTS=1

at the top and:

sleep $((1*NUM_EVENTS))

here?

Use of "sleep" in tests worries me because they are generally meant to
"avoid" races in the underlying test programs but the amount of time to
sleep makes timing assumptions about the system's ability to run the
tests pieces.

However, sleep is highly practical while closing all possible races in
test scripts make the code much more complicated. Hence I personally
like to see these uses of "sleep" commented.

In this case, depending on the system, load, and the number of events
generated this sleep may not be sufficient. If there's other load on
this system or if it's running on a virtual machine then pec_listener
may not have enough time to process all of the events (from
event_generator or otherwise) before receiving the signal. Unlikely I
expect, but possible...

> > +   kill -s SIGINT $pid 2> /dev/null

This worries me a little.

I think we need to ensure that pec_listener has flushed its buffers
before we kill it -- otherwise sometimes we may get false FAIL results.
You already have pec_listener catch this signal and exit. The only
missing part is the fsync().

> > +   wait $pid
> > +   ret2=$?
> > +
> > +   if [ $ret1 -ne 0 -o ! -s "$log/generator_$1.log" ]; then
> > +           tst_resm TFAIL "failed to generate process events"
> > +           exit_status=1
> > +           return 1
> > +   fi
> > +
> > +   if [ $ret2 -ne 0 ]; then
> > +           tst_resm TFAIL "failed to listen process events"
> > +           exit_status=1
> > +           return 1
> > +   fi
> > +
> > +   event="`cat $log/generator_$1.log`"
> > +   cat "$log/listener_$1.log" | grep "$event" > /dev/null
> > +   if [ $? -eq 0 ]; then
> > +           tst_resm TPASS "get event - $event"
> > +   else
> > +           tst_resm TFAIL "expected event - $event"
> > +           exit_status=1
> > +   fi
> > +}
> > +
> > +run_case 1 "fork"
> > +run_case 2 "exec"
> > +run_case 3 "exit"
> > +run_case 4 "uid"
> > +run_case 5 "gid"
> > +

At the top of this script you could put:

        EVENT_TEST_CASES=( "fork" "exec" "exit" "uid" "gid" )
        [EMAIL PROTECTED]

Then you could replace the "run_case" invokations with:

        i=0
        for CASE in "[EMAIL PROTECTED]" ; do
                run_case $i $CASE
                ((i++))
        done

I don't see any significant issues -- just a couple obscure problems
folks aren't very likely to encounter. Personally, I think these tests
will be a valuable addition to LTP. Thanks for writing them!

Cheers,
        -Matt Helsley


-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to