/* signal_after_exec.c */ /* by Vince Weaver vweaver1 _at_ eecs.utk.edu */ /* Compile with gcc -O2 -Wall -o signal_after_exec signal_after_exec.c */ /* On 2.6.39 and earlier the execd process gets no signals */ /* On 3.0 and normal it does, which quickly kills the program with SIGIO */ #define _GNU_SOURCE 1 #include #include #include #include #include #include #include #include #include #include #include "perf_event.h" int perf_event_open(struct perf_event_attr *hw_event_uptr, pid_t pid, int cpu, int group_fd, unsigned long flags) { return syscall(__NR_perf_event_open,hw_event_uptr, pid, cpu, group_fd, flags); } static int count=0; static void our_handler(int signum,siginfo_t *oh, void *blah) { int ret,fd1; fd1=oh->si_fd; ret=ioctl(fd1, PERF_EVENT_IOC_DISABLE,0); count++; ret=ioctl(fd1, PERF_EVENT_IOC_REFRESH,1); } double busywork(int count) { int i; double sum=0.0012; for(i=0;i1) { result=busywork(10000000); printf("Count after exec=%d (%lf)\n",count,result); exit(0); } printf("\nOn 2.6.39 and earlier the exec'd process gets no signals.\n"); printf("On 3.0 and later the exec'd process gets a signal, which\n"); printf(" is not handled and it dies with SIGIO.\n\n"); /* set up signal handler */ memset(&sa, 0, sizeof(struct sigaction)); sa.sa_sigaction = our_handler; sa.sa_flags = SA_SIGINFO; if (sigaction( SIGIO, &sa, NULL) < 0) { fprintf(stderr,"Error setting up signal handler\n"); exit(1); } memset(&pe,0,sizeof(struct perf_event_attr)); pe.type=PERF_TYPE_HARDWARE; pe.size=sizeof(struct perf_event_attr); pe.config=PERF_COUNT_HW_INSTRUCTIONS; pe.sample_period=100000; pe.sample_type=PERF_SAMPLE_IP; pe.read_format=0; pe.disabled=1; pe.pinned=1; pe.wakeup_events=1; fd=perf_event_open(&pe,0,-1,-1,0); if (fd<0) { fprintf(stderr,"Error opening\n"); exit(1); } void *blargh; blargh=mmap(NULL, (1+1)*4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); /* setup event 2 to have overflow signals */ fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); fcntl(fd, F_SETSIG, SIGIO); fcntl(fd, F_SETOWN,getpid()); ioctl(fd, PERF_EVENT_IOC_RESET, 0); /* enable counting */ ret=ioctl(fd, PERF_EVENT_IOC_ENABLE,0); result=busywork(10000000); printf("Count before exec=%d (%lf)\n",count,result); /* exec ourselves, but call a busy function */ execl(argv[0],argv[0],"busy",NULL); return 0; }