Is it correct to use pulseIn() in ISRs?
It is quite OK to use millis() or micros() inside an ISR. In fact that is an excellent time to do it, because you are recording the time of the event shortly after it happened. Make sure the variable you are saving it to is unsigned long and volatile. Eg.

volatile unsigned long whenItHappened;
volatile bool eventHappened;

void myISR ()
  {
  whenItHappened = millis ();
  eventHappened = true;
  }


Now in your main loop you can test the eventHappened flag, so you will know if this event has happened, and whenItHappened is when.

It is not a good idea to use pulseIn() because that can wait quite a long time for a pulse. The default timeout for pulseIn is 1 second, which is far too long to wait inside an ISR.

If you want to time something (eg. how long it takes a ball to cross a sensor) use the interrupt twice, once to find the first event, and again to find the second.



Example

Example code which times how long a ball passes a sensor:

const byte LED = 12;
const byte photoTransistor = 2;

unsigned long startTime;
volatile unsigned long elapsedTime;
volatile boolean done;

void ballPasses ()
{
  // if low, ball is in front of light
  if (digitalRead (photoTransistor) == LOW)
    {
    startTime = micros (); 
    }
  else
    {
    elapsedTime = micros () - startTime;  
    done = true;
    }

  digitalWrite (LED, !digitalRead (LED));  
}


void setup ()
{
  Serial.begin (115200);
  Serial.println ("Timer sketch started.");  
  pinMode (LED, OUTPUT);
  attachInterrupt (0, ballPasses, CHANGE);
}

void loop ()
  {
  if (!done)
    return;

  Serial.print ("Time taken = ");
  Serial.print (elapsedTime);
  Serial.println (" uS");
  done = false;
  }


That code used micros() for a more accurate timing.



Reference


Interrupts