From 4f9727326e8ac36728d7a8f01e2a2f754273c864 Mon Sep 17 00:00:00 2001
From: Craig Tiller <ctiller@google.com>
Date: Thu, 5 Feb 2015 12:40:20 -0800
Subject: [PATCH] Fix memory usage

---
 include/grpc/grpc.h                                |  8 ++++++--
 src/core/surface/call.c                            | 10 +++++-----
 src/core/surface/metadata_array.c                  |  5 -----
 test/core/end2end/tests/generate_tests.py          | 14 ++++++++++++++
 .../end2end/tests/request_response_with_payload.c  |  8 +++++++-
 test/core/end2end/tests/simple_request.c           |  8 +++++++-
 6 files changed, 39 insertions(+), 14 deletions(-)
 create mode 100755 test/core/end2end/tests/generate_tests.py

diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 444f979fd4..89cccab3d2 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -177,8 +177,8 @@ void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader);
 
 /* A single metadata element */
 typedef struct grpc_metadata {
-  char *key;
-  char *value;
+  const char *key;
+  const char *value;
   size_t value_length;
 } grpc_metadata;
 
@@ -292,9 +292,13 @@ typedef struct grpc_op {
       grpc_status_code status;
       const char *status_details;
     } send_status_from_server;
+    /* ownership of the array is with the caller, but ownership of the elements
+       stays with the call object */
     grpc_metadata_array *recv_initial_metadata;
     grpc_byte_buffer **recv_message;
     struct {
+      /* ownership of the array is with the caller, but ownership of the elements
+         stays with the call object */
       grpc_metadata_array *trailing_metadata;
       grpc_status_code *status;
       char **status_details;
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
index 1657edb3de..b47d5f4aec 100644
--- a/src/core/surface/call.c
+++ b/src/core/surface/call.c
@@ -908,8 +908,8 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) {
           gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity);
     }
     mdusr = &dest->metadata[dest->count++];
-    mdusr->key = (char *)grpc_mdstr_as_c_string(md->key);
-    mdusr->value = (char *)grpc_mdstr_as_c_string(md->value);
+    mdusr->key = grpc_mdstr_as_c_string(md->key);
+    mdusr->value = grpc_mdstr_as_c_string(md->value);
     mdusr->value_length = GPR_SLICE_LENGTH(md->value->slice);
     if (call->owned_metadata_count == call->owned_metadata_capacity) {
       call->owned_metadata_capacity = GPR_MAX(
@@ -1089,8 +1089,8 @@ static void destroy_legacy_state(legacy_state *ls) {
   size_t i, j;
   for (i = 0; i < 2; i++) {
     for (j = 0; j < ls->md_out_count[i]; j++) {
-      gpr_free(ls->md_out[i][j].key);
-      gpr_free(ls->md_out[i][j].value);
+      gpr_free((char *)ls->md_out[i][j].key);
+      gpr_free((char *)ls->md_out[i][j].value);
     }
     gpr_free(ls->md_out[i]);
   }
@@ -1123,7 +1123,7 @@ grpc_call_error grpc_call_add_metadata_old(grpc_call *call,
   mdout->key = gpr_strdup(metadata->key);
   mdout->value = gpr_malloc(metadata->value_length);
   mdout->value_length = metadata->value_length;
-  memcpy(mdout->value, metadata->value, metadata->value_length);
+  memcpy((char *)mdout->value, metadata->value, metadata->value_length);
 
   unlock(call);
 
diff --git a/src/core/surface/metadata_array.c b/src/core/surface/metadata_array.c
index 257ff1f820..7a230037d5 100644
--- a/src/core/surface/metadata_array.c
+++ b/src/core/surface/metadata_array.c
@@ -8,10 +8,5 @@ void grpc_metadata_array_init(grpc_metadata_array *array) {
 }
 
 void grpc_metadata_array_destroy(grpc_metadata_array *array) {
-  size_t i;
-  for (i = 0; i < array->count; i++) {
-    gpr_free(array->metadata[i].key);
-    gpr_free(array->metadata[i].value);
-  }
   gpr_free(array->metadata);
 }
diff --git a/test/core/end2end/tests/generate_tests.py b/test/core/end2end/tests/generate_tests.py
new file mode 100755
index 0000000000..5f9b00b4c9
--- /dev/null
+++ b/test/core/end2end/tests/generate_tests.py
@@ -0,0 +1,14 @@
+#!/usr/bin/python2.7
+
+import copy
+
+class State(object):
+
+  pass
+
+
+def generate(state):
+  for op, 
+
+generate(State())
+
diff --git a/test/core/end2end/tests/request_response_with_payload.c b/test/core/end2end/tests/request_response_with_payload.c
index 294a3fc907..30e96def3e 100644
--- a/test/core/end2end/tests/request_response_with_payload.c
+++ b/test/core/end2end/tests/request_response_with_payload.c
@@ -124,7 +124,7 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) {
   grpc_call_details call_details;
   grpc_status_code status;
   char *details = NULL;
-  size_t details_capacity = NULL;
+  size_t details_capacity = 0;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com",
@@ -200,6 +200,12 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) {
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
   GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));
 
+  gpr_free(details);
+  grpc_metadata_array_destroy(&initial_metadata_recv);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+
   grpc_call_destroy(c);
   grpc_call_destroy(s);
 
diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c
index 1d070795c1..34a3f99916 100644
--- a/test/core/end2end/tests/simple_request.c
+++ b/test/core/end2end/tests/simple_request.c
@@ -118,7 +118,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
   grpc_call_details call_details;
   grpc_status_code status;
   char *details = NULL;
-  size_t details_capacity = NULL;
+  size_t details_capacity = 0;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com",
@@ -180,6 +180,12 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
   GPR_ASSERT(0 == strcmp(call_details.host, "test.google.com"));
   GPR_ASSERT(was_cancelled == 1);
 
+  gpr_free(details);
+  grpc_metadata_array_destroy(&initial_metadata_recv);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+
   grpc_call_destroy(c);
   grpc_call_destroy(s);
 
-- 
GitLab