template <bool ManualReset> void AsyncWaitHandleDestructRaceCallback() { auto wh = make_shared<AsyncWaitHandle<ManualReset>>(); AutoResetEvent callbackCanStart(false); AutoResetEvent resultEvent(false); wh->BeginWaitOne( TimeSpan::MaxValue, [&resultEvent, &callbackCanStart] (AsyncOperationSPtr const & op) mutable { Trace.WriteInfo(TraceType, "callback waiting for action"); callbackCanStart.WaitOne(); Trace.WriteInfo(TraceType, "callback starting action"); ErrorCode result = op->End(op); VERIFY_IS_TRUE(result.IsSuccess()); resultEvent.Set(); Trace.WriteInfo(TraceType, "leaving callback"); }, AsyncOperationSPtr()); //make wh destruction and callback race wh->Set(); wh.reset(); callbackCanStart.Set(); BOOST_REQUIRE(resultEvent.WaitOne(TimeSpan::FromSeconds(60))); }
int pgQueryThread::RaiseEvent(int _retval) { #if !defined(PGSCLI) if (m_caller) { pgQueryResultEvent resultEvent(GetId(), m_queries[m_currIndex], m_queries[m_currIndex]->m_eventID); // client data resultEvent.SetClientData(m_queries[m_currIndex]->m_data); resultEvent.SetInt(_retval); m_caller->AddPendingEvent(resultEvent); } #endif return _retval; }
void pgsApplication::Complete() { // If last_error_line() == -1 then there was no error // Else get the line number where the error occurred m_last_error_line = m_thread->last_error_line(); #if !defined(PGSCLI) if (m_caller != 0) { wxCommandEvent resultEvent(wxEVT_COMMAND_MENU_SELECTED, m_event_id); m_caller->AddPendingEvent(resultEvent); } #endif // PGSCLI wxLogScript(wxT("Execution completed")); }
int pgQueryThread::raiseEvent(int retval) { if (caller) { #if !defined(PGSCLI) wxCommandEvent resultEvent(wxEVT_COMMAND_MENU_SELECTED, eventId); resultEvent.SetClientData(data); #if wxCHECK_VERSION(2, 9, 0) caller->GetEventHandler()->AddPendingEvent(resultEvent); #else caller->AddPendingEvent(resultEvent); #endif #endif } return retval; }
template <bool ManualReset> void AsyncWaitHandleSetBeforeWait() { AsyncWaitHandle<ManualReset> asyncWaitHandle(true); AutoResetEvent resultEvent(false); asyncWaitHandle.BeginWaitOne( TimeSpan::MaxValue, [&asyncWaitHandle, &resultEvent] (AsyncOperationSPtr const & op) { ErrorCode result = asyncWaitHandle.EndWaitOne(op); VERIFY_IS_TRUE(result.IsSuccess()); resultEvent.Set(); }, AsyncOperationSPtr()); BOOST_REQUIRE(resultEvent.WaitOne(TimeSpan::FromSeconds(60))); }
void *dbgPgThread::Entry( void ) { wxLogInfo( wxT( "worker thread waiting for some work to do..." )); // This thread should hang at the call to m_condition.Wait() // When m_condition is signaled, we wake up, send a command // to the PostgreSQL server, and wait for a result. while( m_queueCounter.Wait() == wxSEMA_NO_ERROR && !die && !TestDestroy() ) { m_owner.setNoticeHandler( noticeHandler, this ); m_currentCommand = getNextCommand(); wxString command = m_currentCommand->getCommand(); wxLogInfo( wxT( "Executing: %s" ), command.c_str()); // This call to PQexec() will hang until we've received // a complete result set from the server. PGresult *result = 0; #if defined (__WXMSW__) || (EDB_LIBPQ) // If we have a set of params, and we have the required functions... dbgPgParams *params = m_currentCommand->getParams(); bool use_callable = true; // we do not need all of PQi stuff AS90 onwards if (m_owner.EdbMinimumVersion(9, 0)) use_callable = false; #ifdef EDB_LIBPQ if (params && use_callable) #else if (PQiGetOutResult && PQiPrepareOut && PQiSendQueryPreparedOut && params && use_callable) #endif { wxLogInfo(wxT("Using an EnterpriseDB callable statement")); wxString stmt = wxString::Format(wxT("DebugStmt-%d-%d"), this->GetId(), ++run); PGresult *res = PQiPrepareOut(m_owner.getConnection(), stmt.mb_str(wxConvUTF8), command.mb_str(wxConvUTF8), params->nParams, params->paramTypes, params->paramModes); if( PQresultStatus(res) != PGRES_COMMAND_OK) { wxLogError(_( "Could not prepare the callable statement: %s, error: %s" ), stmt.c_str(), wxString(PQresultErrorMessage(res), *conv).c_str()); PQclear(res); return this; } int ret = PQiSendQueryPreparedOut(m_owner.getConnection(), stmt.mb_str(wxConvUTF8), params->nParams, params->paramValues, NULL, // Can be null - all params are text NULL, // Can be null - all params are text 1); if (ret != 1) { wxLogError(_( "Couldn't execute the callable statement: %s" ), stmt.c_str()); PQclear(res); return this; } // We need to call PQgetResult before we can call PQgetOutResult // Note that this is all async code as far as libpq is concerned to // ensure we can always bail out when required, without leaving threads // hanging around. PGresult *dummy; while(true) { if (die || TestDestroy()) { PQrequestCancel(m_owner.getConnection()); return this; } PQconsumeInput(m_owner.getConnection()); if (PQisBusy(m_owner.getConnection())) { Yield(); wxMilliSleep(10); continue; } dummy = PQgetResult(m_owner.getConnection()); // There should be 2 results - the first is the dummy, the second // contains our out params. if (dummy) break; } if((PQresultStatus(dummy) == PGRES_NONFATAL_ERROR) || (PQresultStatus(dummy) == PGRES_FATAL_ERROR)) result = dummy; else { PQclear(dummy); result = PQiGetOutResult(m_owner.getConnection()); } } else { #endif // This is the normal case for a pl/pgsql function, or if we don't // have access to PQgetOutResult. // Note that this is all async code as far as libpq is concerned to // ensure we can always bail out when required, without leaving threads // hanging around. int ret = PQsendQuery(m_owner.getConnection(), command.mb_str(wxConvUTF8)); if (ret != 1) { wxLogError(_( "Couldn't execute the query (%s): %s" ), command.c_str(), wxString(PQerrorMessage(m_owner.getConnection()), *conv).c_str()); return this; } PGresult *part; while(true) { if (die || TestDestroy()) { PQrequestCancel(m_owner.getConnection()); return this; } PQconsumeInput(m_owner.getConnection()); if (PQisBusy(m_owner.getConnection())) { Yield(); wxMilliSleep(10); continue; } // In theory we should only get one result here, but we'll loop // anyway until we get the last one. part = PQgetResult(m_owner.getConnection()); if (!part) break; result = part; } #if defined (__WXMSW__) || (EDB_LIBPQ) } #endif if(!result) { wxLogInfo(wxT( "NULL PGresult - user abort?" )); return this; } wxLogInfo(wxT( "Complete: %s" ), wxString(PQresStatus(PQresultStatus(result)), *conv).c_str()); // Notify the GUI thread that a result set is ready for display if( m_currentCommand->getEventType() == wxEVT_NULL ) { wxCommandEvent resultEvent( wxEVT_COMMAND_MENU_SELECTED, RESULT_ID_DIRECT_TARGET_COMPLETE ); resultEvent.SetClientData( result ); m_currentCommand->getCaller()->AddPendingEvent( resultEvent ); } else { wxCommandEvent resultEvent( wxEVT_COMMAND_MENU_SELECTED, m_currentCommand->getEventType()); resultEvent.SetClientData( result ); m_currentCommand->getCaller()->AddPendingEvent( resultEvent ); } } return this; }