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"));
}
Exemple #4
0
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)));
    }
Exemple #6
0
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;
}