Branch: Tag:

2017-06-03

2017-06-03 10:46:54 by Stephen R. van den Berg <srb@cuci.nl>

pgsql: Add instrumentation to aid in diagnosing raceconditions.

66:    return Regexp(ret->read());   }    - final void closestatement(bufcon|conxion plugbuffer,string oldprep) { + final void closestatement(bufcon|conxsess plugbuffer,string oldprep) {    if(oldprep) {    PD("Close statement %s\n",oldprep); -  plugbuffer->add_int8('C')->add_hstring(({'S',oldprep,0}),4,4); +  CHAIN(plugbuffer)->add_int8('C')->add_hstring(({'S', oldprep, 0}), 4, 4);    }   }   
151:   class bufcon {    inherit Stdio.Buffer;    + #ifdef PG_DEBUGRACE +  final bufcon `chain() { +  return this; +  } + #endif +     private conxion realbuffer;       protected void create(conxion _realbuffer) {
181:    lock=0;    this->clear();    if(lock=realbuffer->nostash->trylock(1)) { -  realbuffer->started=lock; lock=0; + #ifdef PG_DEBUGRACE +  conxsess sess = conxsess(realbuffer); +  realbuffer->started = lock; +  lock = 0; +  sess->sendcmd(SENDOUT); + #else +  realbuffer->started = lock; +  lock = 0;    realbuffer->sendcmd(SENDOUT); -  + #endif    }    } -  +    };      class conxiin {
255:    final int stashflushmode;    final int stashcount;    final int synctransact; + #ifdef PG_DEBUGRACE +  final mixed nostrack; + #endif   #ifdef PG_DEBUG    final int queueoutidx;    final int queueinidx=-1;
266:    portal._portalname,++queueoutidx,synctransact,sizeof(this));    }    -  final conxion|bufcon start(void|int waitforreal) { +  final bufcon|conxsess start(void|int waitforreal) {    Thread.MutexKey lock;    if(lock=(waitforreal?nostash->lock:nostash->trylock)(1)) { -  started=lock; + #ifdef PG_DEBUGRACE +  conxsess sess = conxsess(this); + #endif +  started = lock;    lock=shortmux->lock();    if(stashcount)    PT(stashavail.wait(lock));
277:    foreach(stashqueue->try_read_array();;sql_result portal)    queueup(portal);    lock=0; + #ifdef PG_DEBUGRACE +  return sess; + #else    return this; -  + #endif    }    stashcount++;    return bufcon(this);
449:    if(socket)    catch(fd=socket->query_fd());    res=predef::sprintf("conxion fd: %d input queue: %d/%d " -  "queued portals: %d output queue: %d/%d\n", +  "queued portals: %d output queue: %d/%d\n" +  "started: %d\n",    fd,sizeof(i),i->_size_object(), -  qportals->size(),sizeof(this),_size_object()); +  qportals->size(),sizeof(this),_size_object(), +  !!started);    break;    }    return res;
473:    }   };    + #ifdef PG_DEBUGRACE + class conxsess { +  final conxion chain; +  +  void create(conxion parent) { +  if (parent->started) +  werror("Overwriting conxsess %s %s\n", +  describe_backtrace(({"new ", backtrace()[..<1]})), +  describe_backtrace(({"old ", parent->nostrack}))); +  parent->nostrack = backtrace(); +  chain = parent; +  } +  +  final void sendcmd(int mode,void|sql_result portal) { +  chain->sendcmd(mode, portal); +  chain = 0; +  } +  +  void destroy() { +  if (chain) +  werror("Untransmitted conxsess %s\n", +  describe_backtrace(({"", backtrace()[..<1]}))); +  } + }; + #endif +    //! The result object returned by @[Sql.pgsql()->big_query()], except for   //! the noted differences it behaves the same as @[Sql.sql_result].   //!
892:    PD("Bind portal %O statement %O\n",_portalname,_preparedname);    _fetchlimit=pgsqlsess->_fetchlimit;    _openportal(); -  conxion bindbuffer=c->start(); +  conxsess bindbuffer = c->start();    _unnamedstatementkey=0; -  bindbuffer->add_int8('B')->add_hstring(plugbuffer,4,4); +  CHAIN(bindbuffer)->add_int8('B')->add_hstring(plugbuffer, 4, 4);    if(!_tprepared && sizeof(_preparedname)) -  closestatement(bindbuffer,_preparedname); +  closestatement(CHAIN(bindbuffer), _preparedname);    _sendexecute(_fetchlimit    && !(cachealways[_query]    || sizeof(_query)>=MINPREPARELENGTH &&
938:    releaseconditions();    }    -  final int _closeportal(bufcon plugbuffer) { +  final int _closeportal(conxsess cs) { +  object plugbuffer = CHAIN(cs);    int retval=KEEP;    PD("%O Try Closeportal %d\n",_portalname,_state);    Thread.MutexKey lock=closemux->lock();
1021:    if(statusccomplete && !statuscmdcomplete)    statuscmdcomplete=statusccomplete;    inflight=0; -  catch { -  conxion plugbuffer=c->start(); +  conxsess plugbuffer; +  if (!catch(plugbuffer = c->start()))    plugbuffer->sendcmd(_closeportal(plugbuffer)); -  }; +     _state=CLOSED;    datarows->write(1); // Signal EOF    releaseconditions();
1036:    };    }    -  final void _sendexecute(int fetchlimit,void|bufcon plugbuffer) { +  final void _sendexecute(int fetchlimit,void|bufcon|conxsess plugbuffer) {    int flushmode;    PD("Execute portal %O fetchlimit %d\n",_portalname,fetchlimit);    if(!plugbuffer)    plugbuffer=c->start(1); -  plugbuffer->add_int8('E')->add_hstring(({_portalname,0}),4,8) +  CHAIN(plugbuffer)->add_int8('E')->add_hstring(({_portalname,0}), 4, 8)    ->add_int32(fetchlimit);    if(!fetchlimit)    flushmode=_closeportal(plugbuffer)==SYNCSEND?SYNCSEND:FLUSHSEND;
1119:    trydelayederror();    if(copydata) {    PD("CopyData\n"); -  c->start()->add_int8('d')->add_hstring(copydata,4,4)->sendcmd(SENDOUT); +  object cs = c->start(); +  CHAIN(cs)->add_int8('d')->add_hstring(copydata, 4, 4); +  cs->sendcmd(SENDOUT);    } else    _releasesession();    }