Another Millis Timer off question...

UKHeliBob:
millis() is constantly updated but you only capture the start time when an event happens

One important thing to note is that the event in question is an input becoming released, not when it is released, which will be most of the time.

I get what you're saying. Perhaps something along these lines will work?

int buttonPin = 2; //input pin 2
int valveOut = 3;  //output pin 3
int welderOut = 4; //output pin 4
int buttonState = 0;  //variable
int lastButtonState = 0;  //variable

unsigned long postFlow = 3000;  //gas after flow time
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

void setup() {
  pinMode (buttonPin, INPUT_PULLUP);
  pinMode (valveOut, OUTPUT);
  pinMode (welderOut, OUTPUT);
  digitalWrite(valveOut, HIGH);
  digitalWrite(welderOut, HIGH);
}

void loop() {
  // read the push button
  buttonState = digitalRead(buttonPin);

  // if the state has changed
  if (buttonState != lastButtonState) {

    // if the state is LOW then the button went from OFF to ON
    if (buttonState == LOW) {
      lastButtonState = buttonState;
      // turn on welder & gas valve
      digitalWrite(welderOut, LOW);
      valveOut, LOW;
      // if the state is HIGH, then button went from ON to OFF
    } else if (buttonState == HIGH) {
      lastButtonState = buttonState;
      currentMillis = millis(); // grab current time
      digitalWrite(welderOut, HIGH); // turn off welder
      // check time & compare to postFlow
      if (currentMillis - previousMillis >= postFlow)
        digitalWrite(valveOut, LOW); // turn on valve
      previousMillis = currentMillis;
    } else { // if time has elapsed
      digitalWrite(valveOut, HIGH); // turn off valve
    }
  }
}