Changeset: 3ae93365d2f4 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=3ae93365d2f4 Modified Files: gdk/gdk_tracer.c Branch: default Log Message:
Fix locking. If you unlock and then lock again, you have to check everything again since another thread might have gotten inbetween. Avoid this by keeping the lock. diffs (202 lines): diff --git a/gdk/gdk_tracer.c b/gdk/gdk_tracer.c --- a/gdk/gdk_tracer.c +++ b/gdk/gdk_tracer.c @@ -184,6 +184,56 @@ static gdk_return return GDK_SUCCEED; } +static gdk_return +_GDKtracer_flush_buffer_locked(void) +{ + // No reason to flush a buffer with no content + if (active_tracer->allocated_size == 0) { + return GDK_SUCCEED; + } + + if (ATOMIC_GET(&CUR_ADAPTER) == BASIC) { + // Initialize the BASIC adapter. It is used in order to avoid cases with files being + // created and no logs being produced. Even if the creating the file fails the function + // is going to be called only once. + if(!INIT_BASIC_ADAPTER) + _GDKtracer_init_basic_adptr(); + + if (output_file) { + size_t nitems = 1; + size_t w = fwrite(&active_tracer->buffer, active_tracer->allocated_size, nitems, output_file); + + if (w == nitems) + fflush(output_file); + else + // fwrite failed for whatever reason (e.g: disk is full) + if(!LOG_EXC_REP) { + GDK_TRACER_EXCEPTION(GDKTRACER_FAILED "\n"); + LOG_EXC_REP = true; + } + } + + // Reset buffer + memset(active_tracer->buffer, 0, BUFFER_SIZE); + active_tracer->allocated_size = 0; + } else { + memset(active_tracer->buffer, 0, BUFFER_SIZE); + active_tracer->allocated_size = 0; + + // Here we are supposed to send the logs to the profiler + } + + // The file is kept open no matter the adapter + // When GDKtracer stops we need also to close the file + if (GDK_TRACER_STOP && output_file) { + fclose(output_file); + output_file = NULL; + } + + return GDK_SUCCEED; +} + + static inline ADAPTER find_adapter(const char *adptr) { @@ -275,22 +325,20 @@ GDKtracer_reinit_basic(int sig) if ((int) ATOMIC_GET(&CUR_ADAPTER) != BASIC) return; + // Make sure that GDKtracer is not trying to flush the buffer + MT_lock_set(&lock); // BASIC adapter has been initialized already and file is open if(INIT_BASIC_ADAPTER && output_file) { - // Make sure that GDKtracer is not trying to flush the buffer - MT_lock_set(&lock); - { - // Close file - fclose(output_file); - output_file = NULL; - - // Open a new file in append mode - output_file = fopen(file_name, "a"); - if(!output_file) - GDK_TRACER_EXCEPTION(OPENFILE_FAILED); - } - MT_lock_unset(&lock); + // Close file + fclose(output_file); + output_file = NULL; + + // Open a new file in append mode + output_file = fopen(file_name, "a"); + if(!output_file) + GDK_TRACER_EXCEPTION(OPENFILE_FAILED); } + MT_lock_unset(&lock); } @@ -433,13 +481,9 @@ GDKtracer_log(LOG_LEVEL level, const cha // The message fits the buffer OR the buffer is empty but the message does not fit (we cut it off) if (bytes_written < (BUFFER_SIZE - active_tracer->allocated_size) || active_tracer->allocated_size == 0) { active_tracer->allocated_size += bytes_written; - MT_lock_unset(&lock); } else { - MT_lock_unset(&lock); + _GDKtracer_flush_buffer_locked(); - GDKtracer_flush_buffer(); - - MT_lock_set(&lock); va_list va; va_start(va, fmt); bytes_written = _GDKtracer_fill_tracer(active_tracer, fmt, va); @@ -450,9 +494,7 @@ GDKtracer_log(LOG_LEVEL level, const cha // So if the message does not fit we cut it off // message might be > BUFFER_SIZE active_tracer->allocated_size += bytes_written; - MT_lock_unset(&lock); } else { - MT_lock_unset(&lock); // Failed to write to the buffer - bytes_written < 0 if(!LOG_EXC_REP) @@ -463,7 +505,6 @@ GDKtracer_log(LOG_LEVEL level, const cha } } } else { - MT_lock_unset(&lock); // Failed to write to the buffer - bytes_written < 0 if(!LOG_EXC_REP) @@ -480,8 +521,9 @@ GDKtracer_log(LOG_LEVEL level, const cha // and the error is never reported to the user because it // is still in the buffer which it never gets flushed. if (level == CUR_FLUSH_LEVEL || level == M_CRITICAL || level == M_ERROR) { - GDKtracer_flush_buffer(); + _GDKtracer_flush_buffer_locked(); } + MT_lock_unset(&lock); return GDK_SUCCEED; } @@ -489,59 +531,13 @@ GDKtracer_log(LOG_LEVEL level, const cha gdk_return GDKtracer_flush_buffer(void) { + gdk_return rc; + // No reason to flush a buffer with no content MT_lock_set(&lock); - if (active_tracer->allocated_size == 0) { - MT_lock_unset(&lock); - return GDK_SUCCEED; - } + rc = _GDKtracer_flush_buffer_locked(); MT_lock_unset(&lock); - - if (ATOMIC_GET(&CUR_ADAPTER) == BASIC) { - // Initialize the BASIC adapter. It is used in order to avoid cases with files being - // created and no logs being produced. Even if the creating the file fails the function - // is going to be called only once. - if(!INIT_BASIC_ADAPTER) - _GDKtracer_init_basic_adptr(); - - MT_lock_set(&lock); - { - if (output_file) { - size_t nitems = 1; - size_t w = fwrite(&active_tracer->buffer, active_tracer->allocated_size, nitems, output_file); - - if (w == nitems) - fflush(output_file); - else - // fwrite failed for whatever reason (e.g: disk is full) - if(!LOG_EXC_REP) - { - GDK_TRACER_EXCEPTION(GDKTRACER_FAILED "\n"); - LOG_EXC_REP = true; - } - } - - // Reset buffer - memset(active_tracer->buffer, 0, BUFFER_SIZE); - active_tracer->allocated_size = 0; - } - MT_lock_unset(&lock); - } else { - MT_lock_set(&lock); - memset(active_tracer->buffer, 0, BUFFER_SIZE); - active_tracer->allocated_size = 0; - MT_lock_unset(&lock); - - // Here we are supposed to send the logs to the profiler - } - - // The file is kept open no matter the adapter - // When GDKtracer stops we need also to close the file - if (GDK_TRACER_STOP) - if (output_file) - fclose(output_file); - - return GDK_SUCCEED; + return rc; } _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list