Processes execute requests to produce an execute reply message, as well as related messages to send back display data, stdout/stderr streams, and busy/idle messages.
function processMessage(message) {
  var complete = false;
  function outputHandler(name, str) {
    if (!complete) {
      var streamMessage = messages.stream(message, name, str);
      messages.write(streamMessage, _session.io, _session.signer);
    }
  }

  var currentEvaluation = evaluation.create(_session.evaluator, outputHandler);
  var result = currentEvaluation.execute(message.content.code);

  result.then(function(value) {
    // Success ... send the result as display data if there was a result (i.e. don't send back
    // data to render null or undefined)
    if ((value !== undefined) && (value !== null)) {
      var data = display.data(value);
      var dataMessage = messages.data(message, data);
      messages.write(dataMessage, _session.io, _session.signer);
    }

    // Send the execute reply indicating success
    var replyMessage = messages.success(message, currentEvaluation.counter);
    messages.write(replyMessage, _session.shell, _session.signer);
  })
  .fail(function(error) {
    var traceback = null;

    if (error) {
      // Send a trace for the error
      var errorOutput;
      if (error.trace === false) {
        // If an error has been marked as trace suppress, just use the message. This is to
        // communicate error in user's input as opposed to error raised during execution.
        errorOutput = error.message;
      }
      else {
        var trace = _session.evaluator.createTrace(error);
        errorOutput = trace.join('\n');

        // The traceback field of the reply should not contain the error message,
        // just the stack trace.
        traceback = trace.splice(1).map(function(s) { return s.trim().substr(3); });
      }

      var errorMessage = messages.stream(message, 'stderr', errorOutput);
      messages.write(errorMessage, _session.io, _session.signer);
    }
    else {
      error = new Error('Error');
    }

    // Send the execute reply indicating error
    var replyMessage = messages.error(message, currentEvaluation.counter, error, traceback);
    messages.write(replyMessage, _session.shell, _session.signer);
  })
  .fin(function() {
    // Finally process the next message
    processNextMessage(message);
  })
  .done();
}