Merge remote-tracking branch 'origin/topic/bernhard/thread-cleanup'

* origin/topic/bernhard/thread-cleanup:
  and just to be really sure - always make threads go through OnWaitForStop
  hopefully finally fix last interesting race-condition
  it is apparently getting a bit late for changes at important code...
  spoke to soon (forgot to comment in line again).
  Change thread shutdown again to also work with input framework.
  Changing semantics of thread stop methods.
  Support for cleaning up threads that have terminated.
This commit is contained in:
Robin Sommer 2013-05-15 17:16:41 -07:00
commit 639a6410c6
18 changed files with 218 additions and 95 deletions

View file

@ -377,6 +377,38 @@ bool Manager::CreateStream(EnumVal* id, RecordVal* sval)
return true;
}
bool Manager::RemoveStream(EnumVal* id)
{
unsigned int idx = id->AsEnum();
if ( idx >= streams.size() || ! streams[idx] )
return false;
Stream* stream = streams[idx];
if ( ! stream )
return false;
for ( Stream::WriterMap::iterator i = stream->writers.begin(); i != stream->writers.end(); i++ )
{
WriterInfo* winfo = i->second;
DBG_LOG(DBG_LOGGING, "Removed writer '%s' from stream '%s'",
winfo->writer->Name(), stream->name.c_str());
winfo->writer->Stop();
delete winfo->writer;
delete winfo;
}
stream->writers.clear();
delete stream;
streams[idx] = 0;
DBG_LOG(DBG_LOGGING, "Removed logging stream '%s'", stream->name.c_str());
return true;
}
bool Manager::EnableStream(EnumVal* id)
{
Stream* stream = FindStream(id);
@ -1239,25 +1271,17 @@ bool Manager::Flush(EnumVal* id)
return true;
}
void Manager::Terminate()
void Manager::FlushBuffers()
{
// Make sure we process all the pending rotations.
while ( rotations_pending > 0 )
{
thread_mgr->ForceProcessing(); // A blatant layering violation ...
usleep(1000);
}
if ( rotations_pending < 0 )
reporter->InternalError("Negative pending log rotations: %d", rotations_pending);
// Flush out cached entries in Frontend
for ( vector<Stream *>::iterator s = streams.begin(); s != streams.end(); ++s )
{
if ( ! *s )
continue;
Flush((*s)->id);
for ( Stream::WriterMap::iterator i = (*s)->writers.begin();
i != (*s)->writers.end(); i++ )
i->second->writer->FlushWriteBuffer();
}
}

View file

@ -47,6 +47,16 @@ public:
*/
bool CreateStream(EnumVal* id, RecordVal* stream);
/**
* Remove a log stream, stopping all threads.
*
* @param id The enum value corresponding the log stream.
*
* This methods corresponds directly to the internal BiF defined in
* logging.bif, which just forwards here.
*/
bool RemoveStream(EnumVal* id);
/**
* Enables a log log stream.
*
@ -140,10 +150,10 @@ public:
bool Flush(EnumVal* id);
/**
* Prepares the log manager to terminate. This will flush all log
* stream.
* Flushes all buffers that are currently held by writer frontends
* out to the threads. Does not call the thread flush operation.
*/
void Terminate();
void FlushBuffers();
/**
* Returns a list of supported output formats.

View file

@ -138,6 +138,12 @@ void WriterFrontend::Stop()
{
FlushWriteBuffer();
SetDisable();
if ( backend )
{
backend->SignalStop();
backend = 0; // Thread manager will clean it up once it finishes.
}
}
void WriterFrontend::Init(int arg_num_fields, const Field* const * arg_fields)

View file

@ -54,7 +54,8 @@ public:
/**
* Stops all output to this writer. Calling this methods disables all
* message forwarding to the backend.
* message forwarding to the backend and will eventually remove the
* backend thread.
*
* This method must only be called from the main thread.
*/
@ -207,7 +208,7 @@ protected:
EnumVal* stream;
EnumVal* writer;
WriterBackend* backend; // The backend we have instanatiated.
WriterBackend* backend; // The backend we have instantiated.
bool disabled; // True if disabled.
bool initialized; // True if initialized.
bool buf; // True if buffering is enabled (default).

View file

@ -192,6 +192,8 @@ bool Ascii::DoFinish(double network_time)
abort();
}
DoFlush(network_time);
ascii_done = true;
CloseFile(network_time);