diff --git a/src/core/support/env_posix.c b/src/core/support/env_posix.c
index 4af5aea9b060c505cd691247b3bf636c8eaad70c..79b8fcd7d753afbefdd84210f02e4aaf44c9ab40 100644
--- a/src/core/support/env_posix.c
+++ b/src/core/support/env_posix.c
@@ -54,7 +54,8 @@ char *gpr_getenv(const char *name) {
 }
 
 void gpr_setenv(const char *name, const char *value) {
-  GPR_ASSERT(setenv(name, value, 1) == 0);
+  int res = setenv(name, value, 1);
+  GPR_ASSERT(res == 0);
 }
 
 #endif /* GPR_POSIX_ENV */
diff --git a/src/core/support/env_win32.c b/src/core/support/env_win32.c
index 79644093640ad4a65613ae22f406416eff4518fc..a31fa79d68ea61db226d8591b7aabb56241ceb9b 100644
--- a/src/core/support/env_win32.c
+++ b/src/core/support/env_win32.c
@@ -53,7 +53,8 @@ char *gpr_getenv(const char *name) {
 }
 
 void gpr_setenv(const char *name, const char *value) {
-  GPR_ASSERT(_putenv_s(name, value) == 0);
+  errno_t res = _putenv_s(name, value);
+  GPR_ASSERT(res == 0);
 }
 
 #endif /* GPR_WIN32 */
diff --git a/src/core/support/file.h b/src/core/support/file.h
index a9d81498e5a85b5f29016924124959a7583bf0e6..92f420e7ceb3a64cb27a0d51ddc534cb9c0579c6 100644
--- a/src/core/support/file.h
+++ b/src/core/support/file.h
@@ -48,11 +48,11 @@ extern "C" {
    will be set to 1 in case of success and 0 in case of failure. */
 gpr_slice gpr_load_file(const char *filename, int *success);
 
-/* Creates a temporary file from a template.
-   The last six characters of template must be "XXXXXX" and these are replaced
-   with a string that makes the filename unique.  Since it will be modified,
-   template must not be a string constant. */
-FILE *gpr_tmpfile(char *template);
+/* Creates a temporary file from a prefix.
+   If tmp_filename is not NULL, *tmp_filename is assigned the name of the
+   created file and it is the responsibility of the caller to gpr_free it
+   unless an error occurs in which case it will be set to NULL. */
+FILE *gpr_tmpfile(const char *prefix, char **tmp_filename);
 
 #ifdef __cplusplus
 }
diff --git a/src/core/support/file_posix.c b/src/core/support/file_posix.c
index a156e7703c22a913c027f2019f15bc1f5037e001..a763fbcda2688d99bc374cce1c8f084de20618ae 100644
--- a/src/core/support/file_posix.c
+++ b/src/core/support/file_posix.c
@@ -54,15 +54,26 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
-FILE *gpr_tmpfile(char *template) {
+#include "src/core/support/string.h"
+
+FILE *gpr_tmpfile(const char *prefix, char **tmp_filename) {
   FILE *result = NULL;
-  int fd = mkstemp(template);
+  char *template;
+  int fd;
+
+  if (tmp_filename != NULL) *tmp_filename = NULL;
+
+  gpr_asprintf(&template, "%s_XXXXXX", prefix);
+  GPR_ASSERT(template != NULL);
+
+  fd = mkstemp(template);
   if (fd == -1) {
     gpr_log(GPR_ERROR, "mkstemp failed for template %s with error %s.",
             template, strerror(errno));
-    return NULL;
+    goto end;
   }
   result = fdopen(fd, "w+");
   if (result == NULL) {
@@ -70,6 +81,14 @@ FILE *gpr_tmpfile(char *template) {
             template, fd, strerror(errno));
     unlink(template);
     close(fd);
+    goto end;
+  }
+
+end:
+  if (result != NULL && tmp_filename != NULL) {
+    *tmp_filename = template;
+  } else {
+    gpr_free(template);
   }
   return result;
 }
diff --git a/src/core/support/file_win32.c b/src/core/support/file_win32.c
index b85422c372811dd5914a04a4409b0c1190bab020..d415281e0d37b4e5e13635b5f298998347ca0126 100644
--- a/src/core/support/file_win32.c
+++ b/src/core/support/file_win32.c
@@ -41,24 +41,38 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
-FILE *gpr_tmpfile(char *template) {
+FILE *gpr_tmpfile(const char *prefix, char **tmp_filename) {
   FILE *result = NULL;
+  char *template;
+
+  if (tmp_filename != NULL) *tmp_filename = NULL;
+
+  gpr_asprintf(&template, "%s_XXXXXX", prefix);
+  GPR_ASSERT(template != NULL);
 
   /* _mktemp_s can only create a maximum of 26 file names for any combination of
      base and template values which is kind of sad... We may revisit this
      function later to have something better... */
   if (_mktemp_s(template, strlen(template) + 1) != 0) {
     gpr_log(LOG_ERROR, "Could not create tmp file.");
-    return NULL;
+    goto end;
   }
-  if (fopen_s(&result, template, "wb+") == 0) {
-    return result;
-  } else {
+  if (fopen_s(&result, template, "wb+") != 0) {
     gpr_log(GPR_ERROR, "Could not open file %s", template);
-    return NULL;
+    result = NULL;
+    goto end;
+  }
+
+end:
+  if (result != NULL && tmp_filename != NULL) {
+    *tmp_filename = template;
+  } else {
+    gpr_free(template);
   }
+  return result;
 }
 
 #endif /* GPR_WIN32 */
diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
index 876d35a74b73fb781041e2d485891daf266ea39e..149ac8c07bbb0e5205bc764845801e401f1774ef 100644
--- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
+++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
@@ -139,9 +139,8 @@ int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
 
   /* Set the SSL roots env var. */
-  roots_filename = gpr_strdup("chttp2_simple_ssl_fullstack_test_XXXXXX");
+  roots_file = gpr_tmpfile("chttp2_simple_ssl_fullstack_test", &roots_filename);
   GPR_ASSERT(roots_filename != NULL);
-  roots_file = gpr_tmpfile(roots_filename);
   GPR_ASSERT(roots_file != NULL);
   GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size);
   fclose(roots_file);
diff --git a/test/core/support/file_test.c b/test/core/support/file_test.c
index 1d9fb3ff95a4605faf2734c06a7874b784a2cb39..b089954186c17829b1613354c38b01ea1047d4b9 100644
--- a/test/core/support/file_test.c
+++ b/test/core/support/file_test.c
@@ -44,17 +44,18 @@
 
 #define LOG_TEST_NAME() gpr_log(GPR_INFO, "%s", __FUNCTION__)
 
-static const char template[] = "file_test_XXXXXX";
+static const char prefix[] = "file_test";
 
 static void test_load_empty_file(void) {
   FILE *tmp = NULL;
   gpr_slice slice;
   int success;
-  char *tmp_name = gpr_strdup(template);
+  char *tmp_name;
 
   LOG_TEST_NAME();
 
-  tmp = gpr_tmpfile(tmp_name);
+  tmp = gpr_tmpfile(prefix, &tmp_name);
+  GPR_ASSERT(tmp_name != NULL);
   GPR_ASSERT(tmp != NULL);
   fclose(tmp);
 
@@ -71,17 +72,16 @@ static void test_load_failure(void) {
   FILE *tmp = NULL;
   gpr_slice slice;
   int success;
-  char *tmp_name = gpr_strdup(template);
+  char *tmp_name;
 
   LOG_TEST_NAME();
 
-  tmp = gpr_tmpfile(tmp_name);
+  tmp = gpr_tmpfile(prefix, &tmp_name);
+  GPR_ASSERT(tmp_name != NULL);
   GPR_ASSERT(tmp != NULL);
   fclose(tmp);
   remove(tmp_name);
 
-  GPR_ASSERT(tmp_name != NULL);
-
   slice = gpr_load_file(tmp_name, &success);
   GPR_ASSERT(success == 0);
   GPR_ASSERT(GPR_SLICE_LENGTH(slice) == 0);
@@ -93,12 +93,13 @@ static void test_load_small_file(void) {
   FILE *tmp = NULL;
   gpr_slice slice;
   int success;
-  char *tmp_name = gpr_strdup(template);
+  char *tmp_name;
   const char *blah = "blah";
 
   LOG_TEST_NAME();
 
-  tmp = gpr_tmpfile(tmp_name);
+  tmp = gpr_tmpfile(prefix, &tmp_name);
+  GPR_ASSERT(tmp_name != NULL);
   GPR_ASSERT(tmp != NULL);
   GPR_ASSERT(fwrite(blah, 1, strlen(blah), tmp) == strlen(blah));
   fclose(tmp);
@@ -117,7 +118,7 @@ static void test_load_big_file(void) {
   FILE *tmp = NULL;
   gpr_slice slice;
   int success;
-  char *tmp_name = gpr_strdup(template);
+  char *tmp_name;
   unsigned char buffer[124631];
   unsigned char *current;
   size_t i;
@@ -128,8 +129,9 @@ static void test_load_big_file(void) {
     buffer[i] = 42;
   }
 
-  tmp = gpr_tmpfile(tmp_name);
+  tmp = gpr_tmpfile(prefix, &tmp_name);
   GPR_ASSERT(tmp != NULL);
+  GPR_ASSERT(tmp_name != NULL);
   GPR_ASSERT(fwrite(buffer, 1, sizeof(buffer), tmp) == sizeof(buffer));
   fclose(tmp);