Refcount grpc_alarm object so that grpc_alarm_destroy can safely be called before the alarm event is dequeued from the completion queue

pull/11579/head
Sree Kuchibhotla 8 years ago
parent c8d249ccd2
commit bfce58742d
  1. 1
      BUILD
  2. 1
      build.yaml
  3. 2
      gRPC-Core.podspec
  4. 1
      grpc.gemspec
  5. 1
      package.xml
  6. 72
      src/core/lib/surface/alarm.c
  7. 39
      src/core/lib/surface/alarm_internal.h
  8. 2
      src/core/lib/surface/init.c
  9. 15
      test/core/surface/alarm_test.c
  10. 1
      tools/doxygen/Doxyfile.core.internal
  11. 2
      tools/run_tests/generated/sources_and_headers.json
  12. 1
      vsprojects/vcxproj/grpc/grpc.vcxproj
  13. 3
      vsprojects/vcxproj/grpc/grpc.vcxproj.filters
  14. 1
      vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
  15. 3
      vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
  16. 1
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
  17. 3
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters

@ -645,6 +645,7 @@ grpc_cc_library(
"src/core/lib/slice/slice_hash_table.h",
"src/core/lib/slice/slice_internal.h",
"src/core/lib/slice/slice_string_helpers.h",
"src/core/lib/surface/alarm_internal.h",
"src/core/lib/surface/api_trace.h",
"src/core/lib/surface/call.h",
"src/core/lib/surface/call_test_only.h",

@ -261,6 +261,7 @@ filegroups:
- src/core/lib/slice/slice_hash_table.h
- src/core/lib/slice/slice_internal.h
- src/core/lib/slice/slice_string_helpers.h
- src/core/lib/surface/alarm_internal.h
- src/core/lib/surface/api_trace.h
- src/core/lib/surface/call.h
- src/core/lib/surface/call_test_only.h

@ -325,6 +325,7 @@ Pod::Spec.new do |s|
'src/core/lib/slice/slice_hash_table.h',
'src/core/lib/slice/slice_internal.h',
'src/core/lib/slice/slice_string_helpers.h',
'src/core/lib/surface/alarm_internal.h',
'src/core/lib/surface/api_trace.h',
'src/core/lib/surface/call.h',
'src/core/lib/surface/call_test_only.h',
@ -808,6 +809,7 @@ Pod::Spec.new do |s|
'src/core/lib/slice/slice_hash_table.h',
'src/core/lib/slice/slice_internal.h',
'src/core/lib/slice/slice_string_helpers.h',
'src/core/lib/surface/alarm_internal.h',
'src/core/lib/surface/api_trace.h',
'src/core/lib/surface/call.h',
'src/core/lib/surface/call_test_only.h',

@ -256,6 +256,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/slice/slice_hash_table.h )
s.files += %w( src/core/lib/slice/slice_internal.h )
s.files += %w( src/core/lib/slice/slice_string_helpers.h )
s.files += %w( src/core/lib/surface/alarm_internal.h )
s.files += %w( src/core/lib/surface/api_trace.h )
s.files += %w( src/core/lib/surface/call.h )
s.files += %w( src/core/lib/surface/call_test_only.h )

@ -270,6 +270,7 @@
<file baseinstalldir="/" name="src/core/lib/slice/slice_hash_table.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_internal.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_string_helpers.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/alarm_internal.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/api_trace.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/call.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/call_test_only.h" role="src" />

@ -15,13 +15,19 @@
* limitations under the License.
*
*/
#include "src/core/lib/surface/alarm_internal.h"
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/surface/completion_queue.h"
#ifndef NDEBUG
grpc_tracer_flag grpc_trace_alarm_refcount = GRPC_TRACER_INITIALIZER(false);
#endif
struct grpc_alarm {
gpr_refcount refs;
grpc_timer alarm;
grpc_closure on_alarm;
grpc_cq_completion completion;
@ -31,13 +37,58 @@ struct grpc_alarm {
void *tag;
};
static void do_nothing_end_completion(grpc_exec_ctx *exec_ctx, void *arg,
grpc_cq_completion *c) {}
static void alarm_ref(grpc_alarm *alarm) { gpr_ref(&alarm->refs); }
static void alarm_unref(grpc_alarm *alarm) {
if (gpr_unref(&alarm->refs)) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GRPC_CQ_INTERNAL_UNREF(&exec_ctx, alarm->cq, "alarm");
grpc_exec_ctx_finish(&exec_ctx);
gpr_free(alarm);
}
}
#ifndef NDEBUG
static void alarm_ref_dbg(grpc_alarm *alarm, const char *reason,
const char *file, int line) {
if (GRPC_TRACER_ON(grpc_trace_alarm_refcount)) {
gpr_atm val = gpr_atm_no_barrier_load(&alarm->refs.count);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"Alarm:%p ref %" PRIdPTR " -> %" PRIdPTR " %s", alarm, val,
val + 1, reason);
}
alarm_ref(alarm);
}
static void alarm_unref_dbg(grpc_alarm *alarm, const char *reason,
const char *file, int line) {
if (GRPC_TRACER_ON(grpc_trace_alarm_refcount)) {
gpr_atm val = gpr_atm_no_barrier_load(&alarm->refs.count);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"Alarm:%p Unref %" PRIdPTR " -> %" PRIdPTR " %s", alarm, val,
val - 1, reason);
}
alarm_unref(alarm);
}
#endif
static void alarm_end_completion(grpc_exec_ctx *exec_ctx, void *arg,
grpc_cq_completion *c) {
grpc_alarm *alarm = arg;
GRPC_ALARM_UNREF(alarm, "dequeue-end-op");
}
static void alarm_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
grpc_alarm *alarm = arg;
grpc_cq_end_op(exec_ctx, alarm->cq, alarm->tag, error,
do_nothing_end_completion, NULL, &alarm->completion);
/* We are queuing an op on completion queue. This means, the alarm's structure
cannot be destroyed until the op is dequeued. Adding an extra ref
here and unref'ing when the op is dequeued will achieve this */
GRPC_ALARM_REF(alarm, "queue-end-op");
grpc_cq_end_op(exec_ctx, alarm->cq, alarm->tag, error, alarm_end_completion,
(void *)alarm, &alarm->completion);
}
grpc_alarm *grpc_alarm_create(grpc_completion_queue *cq, gpr_timespec deadline,
@ -45,6 +96,14 @@ grpc_alarm *grpc_alarm_create(grpc_completion_queue *cq, gpr_timespec deadline,
grpc_alarm *alarm = gpr_malloc(sizeof(grpc_alarm));
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
gpr_ref_init(&alarm->refs, 1);
#ifndef NDEBUG
if (GRPC_TRACER_ON(grpc_trace_alarm_refcount)) {
gpr_log(GPR_DEBUG, "Alarm:%p created (ref: 1)", alarm);
}
#endif
GRPC_CQ_INTERNAL_REF(cq, "alarm");
alarm->cq = cq;
alarm->tag = tag;
@ -66,9 +125,6 @@ void grpc_alarm_cancel(grpc_alarm *alarm) {
}
void grpc_alarm_destroy(grpc_alarm *alarm) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_alarm_cancel(alarm);
GRPC_CQ_INTERNAL_UNREF(&exec_ctx, alarm->cq, "alarm");
gpr_free(alarm);
grpc_exec_ctx_finish(&exec_ctx);
GRPC_ALARM_UNREF(alarm, "alarm_destroy");
}

@ -0,0 +1,39 @@
/*
*
* Copyright 2015-2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPC_CORE_LIB_SURFACE_ALARM_INTERNAL_H
#define GRPC_CORE_LIB_SURFACE_ALARM_INTERNAL_H
#include <grpc/support/log.h>
#include "src/core/lib/debug/trace.h"
#ifndef NDEBUG
extern grpc_tracer_flag grpc_trace_alarm_refcount;
#define GRPC_ALARM_REF(a, reason) alarm_ref_dbg(a, reason, __FILE__, __LINE__)
#define GRPC_ALARM_UNREF(a, reason) alarm_unref_dbg(a, reason, __FILE__, __LINE__)
#else /* !defined(NDEBUG) */
#define GRPC_ALARM_REF(a, reason) alarm_ref(a)
#define GRPC_ALARM_UNREF(a, reason) alarm_unref(a)
#endif /* defined(NDEBUG) */
#endif // GRPC_CORE_LIB_SURFACE_ALARM_INTERNAL_H

@ -36,6 +36,7 @@
#include "src/core/lib/iomgr/resource_quota.h"
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/alarm_internal.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/call.h"
#include "src/core/lib/surface/channel_init.h"
@ -137,6 +138,7 @@ void grpc_init(void) {
grpc_register_tracer("call_error", &grpc_call_error_trace);
#ifndef NDEBUG
grpc_register_tracer("pending_tags", &grpc_trace_pending_tags);
grpc_register_tracer("alarm_refcount", &grpc_trace_alarm_refcount);
grpc_register_tracer("queue_refcount", &grpc_trace_cq_refcount);
grpc_register_tracer("closure", &grpc_trace_closure);
grpc_register_tracer("error_refcount", &grpc_trace_error_refcount);

@ -73,6 +73,21 @@ static void test_alarm(void) {
GPR_ASSERT(ev.success == 0);
grpc_alarm_destroy(alarm);
}
{
/* alarm_destroy before cq_next */
grpc_event ev;
void *tag = create_test_tag();
grpc_alarm *alarm =
grpc_alarm_create(cc, grpc_timeout_seconds_to_deadline(2), tag);
grpc_alarm_destroy(alarm);
ev = grpc_completion_queue_next(cc, grpc_timeout_seconds_to_deadline(1),
NULL);
GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
GPR_ASSERT(ev.tag == tag);
GPR_ASSERT(ev.success == 0);
}
shutdown_and_destroy(cc);
}

@ -1332,6 +1332,7 @@ src/core/lib/support/tmpfile_windows.c \
src/core/lib/support/wrap_memcpy.c \
src/core/lib/surface/README.md \
src/core/lib/surface/alarm.c \
src/core/lib/surface/alarm_internal.h \
src/core/lib/surface/api_trace.c \
src/core/lib/surface/api_trace.h \
src/core/lib/surface/byte_buffer.c \

@ -7684,6 +7684,7 @@
"src/core/lib/slice/slice_hash_table.h",
"src/core/lib/slice/slice_internal.h",
"src/core/lib/slice/slice_string_helpers.h",
"src/core/lib/surface/alarm_internal.h",
"src/core/lib/surface/api_trace.h",
"src/core/lib/surface/call.h",
"src/core/lib/surface/call_test_only.h",
@ -7902,6 +7903,7 @@
"src/core/lib/slice/slice_string_helpers.c",
"src/core/lib/slice/slice_string_helpers.h",
"src/core/lib/surface/alarm.c",
"src/core/lib/surface/alarm_internal.h",
"src/core/lib/surface/api_trace.c",
"src/core/lib/surface/api_trace.h",
"src/core/lib/surface/byte_buffer.c",

@ -383,6 +383,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\alarm_internal.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h" />

@ -1094,6 +1094,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h">
<Filter>src\core\lib\slice</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\alarm_internal.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>

@ -278,6 +278,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\alarm_internal.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h" />

@ -827,6 +827,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h">
<Filter>src\core\lib\slice</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\alarm_internal.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>

@ -373,6 +373,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\alarm_internal.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h" />

@ -1004,6 +1004,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h">
<Filter>src\core\lib\slice</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\alarm_internal.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>

Loading…
Cancel
Save