lkml.org 
[lkml]   [2011]   [Aug]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    Subjectperf: overflow signal survives an exec call starting in 3.0
    Hello

    Mark Krentel noticed that starting with Linux 3.0 perf_event signals
    survive a call to exec().

    This means that if you exec() from within a perf-monitored process
    and don't immediately start a signal handler, your process will
    quickly be killed with a SIGIO signal.

    I'm guessing this was an unintended change, although what to do in
    this situation is a bit vague.

    I tediously bisected this to the following commit:

    commit f506b3dc0ec454a16d40cab9ee5d75435b39dc50
    Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Date: Thu May 26 17:02:53 2011 +0200

    perf: Fix SIGIO handling

    Attached is an example program that exhibits the problem.

    Vince
    /* 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 <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    #include <unistd.h>
    #include <fcntl.h>

    #include <signal.h>

    #include <sys/mman.h>

    #include <sys/ioctl.h>

    #include <asm/unistd.h>
    #include <sys/prctl.h>
    #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;i<count;i++) {
    sum+=0.01;
    }
    return sum;

    }


    int main(int argc, char** argv) {

    int fd,ret;
    double result;

    struct perf_event_attr pe;
    struct sigaction sa;

    if (argc>1) {
    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;
    }
    \
     
     \ /
      Last update: 2011-08-23 17:39    [W:4.212 / U:1.440 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site