staticvoidsignal_callback(int signal) { scap_stats s; printf("events captured: %" PRIu64 "\n", g_nevts); scap_get_stats(g_h, &s); printf("seen by driver: %" PRIu64 "\n", s.n_evts); printf("Number of dropped events: %" PRIu64 "\n", s.n_drops); printf("Number of dropped events caused by full buffer: %" PRIu64 "\n", s.n_drops_buffer); printf("Number of dropped events caused by invalid memory access: %" PRIu64 "\n", s.n_drops_pf); printf("Number of dropped events caused by an invalid condition in the kernel instrumentation: %" PRIu64 "\n", s.n_drops_bug); printf("Number of preemptions: %" PRIu64 "\n", s.n_preemptions); printf("Number of events skipped due to the tid being in a set of suppressed tids: %" PRIu64 "\n", s.n_suppressed); printf("Number of threads currently being suppressed: %" PRIu64 "\n", s.n_tids_suppressed); exit(0); }
// // Find out how many devices we have to open, which equals to the number of CPUs // ndevs = sysconf(_SC_NPROCESSORS_ONLN); if(ndevs == -1) { scap_close(handle); snprintf(error, SCAP_LASTERR_SIZE, "_SC_NPROCESSORS_ONLN: %s", scap_strerror(handle, errno)); *rc = SCAP_FAILURE; returnNULL; }
if((handle->m_devs[j].m_fd = open(filename, O_RDWR | O_SYNC)) < 0) { if(errno == ENODEV) { // // This CPU is offline, so we just skip it // continue; } elseif(errno == EBUSY) { uint32_t curr_max_consumers = get_max_consumers(); snprintf(error, SCAP_LASTERR_SIZE, "Too many sysdig instances attached to device %s. Current value for /sys/module/" PROBE_DEVICE_NAME "_probe/parameters/max_consumers is '%"PRIu32"'.", filename, curr_max_consumers); } else { snprintf(error, SCAP_LASTERR_SIZE, "error opening device %s. Make sure you have root credentials and that the " PROBE_NAME " module is loaded.", filename); }
// Set close-on-exec for the fd if (fcntl(handle->m_devs[j].m_fd, F_SETFD, FD_CLOEXEC) == -1) { snprintf(error, SCAP_LASTERR_SIZE, "Can not set close-on-exec flag for fd for device %s (%s)", filename, scap_strerror(handle, errno)); scap_close(handle); *rc = SCAP_FAILURE; returnNULL; }
// // Map the ring buffer // handle->m_devs[j].m_buffer = (char*)mmap(0, len, PROT_READ, MAP_SHARED, handle->m_devs[j].m_fd, 0);
if(handle->m_devs[j].m_buffer == MAP_FAILED) { // we cleanup this fd and then we let scap_close() take care of the other ones close(handle->m_devs[j].m_fd);
scap_close(handle); snprintf(error, SCAP_LASTERR_SIZE, "error mapping the ring buffer for device %s", filename); *rc = SCAP_FAILURE; returnNULL; }
// // Map the ppm_ring_buffer_info that contains the buffer pointers // handle->m_devs[j].m_bufinfo = (struct ppm_ring_buffer_info*)mmap(0, sizeof(struct ppm_ring_buffer_info), PROT_READ | PROT_WRITE, MAP_SHARED, handle->m_devs[j].m_fd, 0);
if(handle->m_devs[j].m_bufinfo == MAP_FAILED) { // we cleanup this fd and then we let scap_close() take care of the other ones munmap(handle->m_devs[j].m_buffer, len); close(handle->m_devs[j].m_fd);
scap_close(handle);
snprintf(error, SCAP_LASTERR_SIZE, "error mapping the ring buffer info for device %s", filename); *rc = SCAP_FAILURE; returnNULL; }
staticinlineint32_tscap_next_live(scap_t* handle, OUT scap_evt** pevent, OUT uint16_t* pcpuid) #else staticint32_tscap_next_live(scap_t* handle, OUT scap_evt** pevent, OUT uint16_t* pcpuid) #endif { #if !defined(HAS_CAPTURE) || defined(CYGWING_AGENT) // // this should be prevented at open time // ASSERT(false); return SCAP_FAILURE; #else uint32_t j; uint64_t max_ts = 0xffffffffffffffffLL; scap_evt* pe = NULL; uint32_t ndevs = handle->m_ndevs;
if(dev->m_sn_len == 0) { // // If we don't have data from this ring, but we are // still occupying, free the resources for the // producer rather than sitting on them. // if(dev->m_lastreadsize > 0) { scap_advance_tail(handle, j); }
else { // // All the buffers have been consumed. Check if there's enough data to keep going or // if we should wait. // return refill_read_buffers(handle); }
int32_t res = scap_readbuf(handle, j, &dev->m_sn_next_event, &dev->m_sn_len);
if(res != SCAP_SUCCESS) { return res; } }
// // Note: we might return a spurious timeout here in case the previous loop extracted valid data to parse. // It's ok, since this is rare and the caller will just call us again after receiving a // SCAP_TIMEOUT. // return SCAP_TIMEOUT; }