Question

The task is to read packets from one tracer and write to many.

I use libtrace_out_t** for output tracers.
Initialization:

uint16_t size = 10;
libtrace_out_t** array = libtrace_out_t*[size];
for(uint16_t i = 0; i < size; ++i) {
   array[i] = trace_create_output(uri); // created OK
   trace_start_output(outTracers_[i]); // started OK
}

// writing packets

Creating, starting and writing packets using elements of tracer's array are fine.
Problems are caused by trace_destroy_output() when I destroy output tracers in loop:

for(uint16_t i = 0; i < size; ++i)  
{  
  if(outTracers_[i])  
     trace_destroy_output(outTracers_[i]);  
}

On the first iteration output tracer is destroying fine.
But on the second it fails with Segmentation fault in

pcap_close(pcap_t* p)

because pointer p has value 0x0.

Can someone explain me why this thing happens or how to destroy it properly?

Was it helpful?

Solution

From the code that you have posted, it looks like you are creating 10 output traces all using the same URI. So, essentially, you've created 10 output files all with the same filename which probably isn't what you intended.

When it comes time to destroy the output traces, the first destroy closes the file matching the name you provided and sets the reference to that file to be NULL. Because the reference is now NULL, any subsequent attempts to destroy that file will cause a segmentation fault.

Make sure you change your URI for each new output trace you create and you should fix the problem.

Example:

/* I prefer pcapfile: over pcap: */
const char *base="pcapfile:output";
uint16_t size = 10;
libtrace_out_t* array[size];
for (uint16_t i = 0; i < size; ++i) {
    char myuri[1024];
    /* First output file will be called output-1.pcap
     * Second output file will be called output-2.pcap
     * And so on...
     */
    snprintf(myuri, 1023, "%s-%u.pcap", base, i);
    array[i] = trace_create_output(uri);
    /* TODO Check for errors here */
    if (trace_start_output(array[i])) {
        /* TODO Handle error case */
    }
}

One other hint: libtrace already includes a tool called tracesplit which takes an input source and splits the packets into multiple output traces based on certain criteria (e.g. number of packets, size of output file, time interval). This tool may already do what you want without having to write code or at least it will act as a good example when writing your own code.

OTHER TIPS

I think you have an out of bounds access in your code

uint16_t size = 5; /// number of tracers
for(uint16_t i = 0; i != size; ++i)  
{  
  if(outTracers_[i])  
     trace_destroy_output(outTracers_[i]);  
}

translates to

for(uint16_t i = 0; i <= 5; ++i)  
{  
  ...
}

And outTracers_[5] is not a valid element in your array

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top