UPSERT statement never completes, infinite loop?
The immediate cause of the infinite loop is this. Per documentation: 


  Note in particular that EXECUTE changes the output of GET DIAGNOSTICS, but does not change FOUND.


But there's more:

CREATE FUNCTION upsert(_ins text, _upd text)
  RETURNS int AS
$func$
DECLARE
   loop_ct int := 0;
   row_ct  int;
BEGIN
LOOP
   IF loop_ct &gt; 1 THEN   -- terminate on 2nd loop
      RETURN 0;
   END  IF;

   EXECUTE _upd;         -- try update
   GET DIAGNOSTICS row_ct = ROW_COUNT;
   IF row_ct &gt; 0 THEN    -- terminate if update successful
      RETURN row_ct;
   END IF;

   BEGIN                 -- try insert
      EXECUTE _ins;
      GET DIAGNOSTICS row_ct = ROW_COUNT;
      RETURN row_ct;
   EXCEPTION WHEN unique_violation THEN
      -- insert violated unique constraint, keep looping
   END;
   loop_ct := loop_ct + 1;
END LOOP;
END
$func$  LANGUAGE plpgsql;


Major points


GET DIAGNOSTICS instead of FOUND, as explained at the outset.
Don't start another block around the UPDATE. Expensive and no use.
I added a feature: on success, the query returns the number of rows affected - at no additional cost since we get the row count anyway. May or may not be useful.


The rest is unchanged, just reformatted.

I have to add a warning about SQL injection. Passing code as text is very susceptible. The code cannot be sanitized. A function like this must be handled with care. Certainly should not be created with SECURITY DEFINER. Related answer:


Issue with composite type in an UPSERT function