diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index 2cf8de0a2d3adce761b2e538ad5feeb8e653ee0a..943d6e4891f65f30d39f89560c44d4be6b41d2c9 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -296,7 +296,11 @@ GRPCAPI grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved); If a status has not been received for the call, set it to the status code and description passed in. Importantly, this function does not send status nor description to the - remote endpoint. */ + remote endpoint. + Note that \a description doesn't need be a static string. + It doesn't need to be alive after the call to + grpc_call_cancel_with_status completes. + */ GRPCAPI grpc_call_error grpc_call_cancel_with_status(grpc_call *call, grpc_status_code status, const char *description, diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 04613f17e3b459d4e2ec46a49a321e6c91538ad7..c57d0894c2974d909e1fd1577bbdedd2e65c2cca 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -644,6 +644,8 @@ static void cancel_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c, static grpc_error *error_from_status(grpc_status_code status, const char *description) { + // copying 'description' is needed to ensure the grpc_call_cancel_with_status + // guarantee that can be short-lived. return grpc_error_set_int( grpc_error_set_str(GRPC_ERROR_CREATE_FROM_COPIED_STRING(description), GRPC_ERROR_STR_GRPC_MESSAGE, diff --git a/test/core/end2end/tests/cancel_with_status.c b/test/core/end2end/tests/cancel_with_status.c index d659d1173a2dc790fb014bb21cc8e79f1f6538c8..fd26fd122e9244c5f7aab5ae46e2774aef1f46b4 100644 --- a/test/core/end2end/tests/cancel_with_status.c +++ b/test/core/end2end/tests/cancel_with_status.c @@ -25,6 +25,7 @@ #include <grpc/grpc.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> +#include <grpc/support/string_util.h> #include <grpc/support/time.h> #include <grpc/support/useful.h> #include "src/core/lib/support/string.h" @@ -138,7 +139,12 @@ static void simple_request_body(grpc_end2end_test_config config, error = grpc_call_start_batch(c, ops, num_ops, tag(1), NULL); GPR_ASSERT(GRPC_CALL_OK == error); - grpc_call_cancel_with_status(c, GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL); + char *dynamic_string = gpr_strdup("xyz"); + grpc_call_cancel_with_status(c, GRPC_STATUS_UNIMPLEMENTED, + (const char *)dynamic_string, NULL); + // The API of \a description allows for it to be a dynamic/non-const + // string, test this guarantee. + gpr_free(dynamic_string); CQ_EXPECT_COMPLETION(cqv, tag(1), 1); cq_verify(cqv);