JDK-7017193 : Small memory leak in get_stack_bounds // os::create_stack_guard_pages
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: hs20
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2011-02-04
  • Updated: 2013-02-26
  • Resolved: 2011-04-25
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 Other
7Fixed hs21Fixed
Related Reports
Relates :  
Relates :  
Description
Valgrind reports small memory leak in get_stack_bounds // os::create_stack_guard_pages.

The reason there is leak is that getline() may return -1 and still allocate memory in str:

    ssize_t len = getline(&str, &dummy, f);
    if (len == -1) {
      fclose(f);
      return false;

Comments
I did some experiments with readline and find it's behaviour inconsistent across platforms and glibc versions. So decided to getrid of it.
22-02-2013

EVALUATION http://hg.openjdk.java.net/jdk7/hotspot-rt/hotspot/rev/677234770800
31-03-2011

SUGGESTED FIX static bool get_stack_bounds(uintptr_t *bottom, uintptr_t *top) { FILE *f = fopen("/proc/self/maps", "r"); if (f == NULL) return false; + char *str = NULL; while (!feof(f)) { size_t dummy; - char *str = NULL; ssize_t len = getline(&str, &dummy, f); if (len == -1) { + free(str); fclose(f); return false; } if (len > 0 && str[len-1] == '\n') { str[len-1] = 0; len--; } static const char *stack_str = "[stack]"; if (len > (ssize_t)strlen(stack_str) && (strcmp(str + len - strlen(stack_str), stack_str) == 0)) { if (sscanf(str, "%" SCNxPTR "-%" SCNxPTR, bottom, top) == 2) { uintptr_t sp = (uintptr_t)__builtin_frame_address(0); if (sp >= *bottom && sp <= *top) { free(str); fclose(f); return true; } } } - free(str); } + free(str); fclose(f); return false; }
14-02-2011

EVALUATION In a product build the leak only occurs once - for the initial thread. For debug builds it occurs for all threads. The docs for getline do not make it clear whether it checks for any available input before allocating the buffer, so we should be conservative and always free on each exit path. Also note that this code is inefficient in that it requires getline to create a new buffer on each call. The buffer could be reused (and resized by getline if needed) on each iteration of the loop and only freed on exit from the method. See suggested fix.
14-02-2011