Bug 5916 - lazymanifest can SIGSEGV when out of memory
Summary: lazymanifest can SIGSEGV when out of memory
Status: RESOLVED FIXED
Alias: None
Product: Mercurial
Classification: Unclassified
Component: Mercurial (show other bugs)
Version: 4.6
Hardware: PC Other
: normal bug
Assignee: Josef "Jeff" Sipek
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-06-13 10:54 UTC by Josef "Jeff" Sipek
Modified: 2018-06-22 00:00 UTC (History)
1 user (show)

See Also:
Python Version: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Josef "Jeff" Sipek 2018-06-13 10:54 UTC
In order to work around hgweb leaking a ton of memory (see bug# 5913), I've wrapped its startup with a ulimit:

(
        ulimit -v 200000
        exec hg serve --webdir-conf /repos/hgweb.config
)

This leads to malloc calls eventually failing.  One of the failure modes I've seen is a SIGSEGV in lazymanifest. 

status: process terminated by SIGSEGV (Segmentation Fault), addr=11

Specifically in:

parsers.so`lazymanifest_dealloc+0x33()
parsers.so`lazymanifest_copy+0xe4()
libpython2.7.so.1.0`PyEval_EvalFrameExReal+0x96e1()
libpython2.7.so.1.0`PyEval_EvalFrameEx+0x19()
libpython2.7.so.1.0`PyEval_EvalCodeEx+0x866()
libpython2.7.so.1.0`PyEval_EvalFrameExReal+0x6877()
libpython2.7.so.1.0`PyEval_EvalFrameEx+0x19()
...

The python version of the stack trace is:

fffffc7fee4f0de0 manifest.py:525 copy()
fffffc7fee4f0240 manifest.py:473 matches()
00000000020b7d30 manifest.py:503 diff()
0000000002bed070 context.py:127 _buildstatus()
0000000001654930 context.py:351 status()
00000000026147b0 localrepo.py:2160 status()
00000000027c41b0 patch.py:2413 diffhunks()
00000000013450b0 webutil.py:545 diffs()
00000000014747f0 templateutil.py:414 flatten()
0000000000f41130 templateutil.py:423 flatten()
0000000003a03370 util.py:1464 increasingchunks()
00000000035797f0 request.py:542 sendresponse()
00000000027e72b0 hgweb_mod.py:308 run_wsgi()
0000000002645830 hgwebdir_mod.py:351 run_wsgi()
0000000002a235f0 server.py:186 do_hgweb()
000000000108e7b0 server.py:95 do_write()
0000000002634cf0 server.py:102 do_POST()
0000000001e43d70 server.py:119 do_GET()
0000000003380330 BaseHTTPServer.py:328 handle_one_request()
0000000002a322b0 BaseHTTPServer.py:340 handle()
0000000001a8c630 SocketServer.py:652 __init__()
fffffc7feca4ade0 server.py:69 __init__()
fffffc7feca55a50 SocketServer.py:331 finish_request()
0000000003761ab0 SocketServer.py:596 process_request_thread()
00000000038cb3b0 threading.py:754 run()
00000000034810b0 threading.py:801 __bootstrap_inner()
0000000002d6d330 threading.py:774 __bootstrap()


lazymanifest_dealloc+0x33 is the 'if (self->lines[i].from_malloc)' condition.  It turns out that at least in one of the crashes I've seen:

1. self != NULL
2. self->numlines == 0x8842
3. self->lines == NULL

The easiest fix is to check for self->lines being non-NULL when executing the for-each-line loop.
Comment 1 HG Bot 2018-06-14 12:40 UTC
Fixed by https://mercurial-scm.org/repo/hg/rev/6caca2a7d37f
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
lazymanifest: don't crash when out of memory (issue5916)

self->lines can be NULL if we failed to allocate memory for it.

(please test the fix)
Comment 2 Bugzilla 2018-06-22 00:00 UTC
Bug was set to TESTING for 7 days, resolving