Arduino Due: Interrupt-based ADC hangs processing
In your interrupt handler, ADC_Handler(), you set sample_buffer_full when the buffer is full.  I don't see anywhere in the code where  sample_buffer_full ever gets reset (cleared) once it's been set.

While sample_buffer_full is set, it disables the body of the interrupt handler – ie, the handler's structure is

if (!sample_buffer_full) { ...body of handler... }


– and in particular, prevents adc_get_latest_value(ADC); from occurring.  The source code of adc_get_latest_value(); is like

uint32_t adc_get_latest_value(const Adc *p_adc) {
  return p_adc-&gt;ADC_LCDR;
}


which accesses the ADC data register.  According to section 43.6.4 Conversion Results on page 1322 of the data sheet, Atmel-11057-32-bit-Cortex-M3-Microcontroller-SAM3X-SAM3A_Datasheet.pdf, 


  The channel EOC bit in the Status Register (ADC_SR) is set and the DRDY is set. In the case of a connected PDC channel, DRDY rising triggers a data transfer request. In any case, either EOC and DRDY can trigger an
  interrupt.
  
  Reading one of the ADC_CDR registers clears the corresponding EOC bit. Reading ADC_LCDR clears the DRDY bit and EOC bit corresponding to the last converted channel.


It appears to me that your code enables interrupts, fills a buffer, sets sample_buffer_full, then spins in ADC_Handler().  That is, repeatedly executes ADC_Handler() without clearing the EOC bit.

Note, for  oscilloscope applications with a Due, I suggest using DMA buffers instead of one interrupt per conversion.  See thread #137635, speed of analogRead, in forum.arduino.cc for DMA code to read one or two analog channels on a Due at one sample per microsecond.  Also see edaboard.com/thread283843 and forum.arduino.cc #186169

Edit note: Although sample_buffer_full does get reset, that reset happens after a time-consuming for-loop.  Whether it takes some hundreds of microseconds or a few milliseconds, the for-loop is enough of a delay that at least one more conversion and interrupt will occur before sample_buffer_full gets cleared.  One unhandled conversion is enough to lock up the interrupt handler.  Here are some alternative approaches to consider:

• Use a circular buffer, and never stop filling it.  This is ok if you are only interested in the most recent data, rather than a complete waveform record.

• Set or reset sample_buffer_full as now; and remove the initial if test from the handler.  Instead, put an if before sample_buffer_idx++;, to not increment if the buffer is full.

• Turn off ADC's freerun mode.  This is a reasonable thing to do when not taking data.

• Turn off ADC's interrupt when not taking data.  Also reasonable.

• Use multiple buffers.  Reasonable, but by itself doesn't avoid the problem.

• Read the latest value every time the handler executes [for example, say int datum = adc_get_latest_value(ADC); as the first statement in the handler] and then only store that value in certain cases.  An easy and effective way to avoid problem.