Skip to content

Instantly share code, notes, and snippets.

@MayamaTakeshi
Created March 20, 2022 23:17
Show Gist options
  • Save MayamaTakeshi/3a163c4ea4a5bf77169b1cd0337340ae to your computer and use it in GitHub Desktop.
Save MayamaTakeshi/3a163c4ea4a5bf77169b1cd0337340ae to your computer and use it in GitHub Desktop.
sip.js memory issue
var sip = require('sip');
var util = require('util');
var os = require('os');
const uuid = require('uuid')
if(process.argv < 3 || !sip.parseUri(process.argv[2])) {
console.error('usage node make_call.js _uri_');
process.exit(1);
}
var uri = process.argv[2]
var config = {
sip_ip: '127.0.0.1',
sip_port: 5040,
}
//starting stack
sip.start({address: config.sip_ip, port: config.sip_port}, function(rq) {
console.log(`got unexpected request`)
console.dir(rq)
process.exit(1)
});
var make_call = function() {
var ref = uuid.v4()
console.log(uri)
var config = {
sip_ip: '127.0.0.1',
sip_port: 5020,
}
sip.send({
method: 'INVITE',
uri: uri,
headers: {
to: "sip:fake_callee@fake.com",
from: "sip:fake_caller@fake.com",
'call-id': ref,
cseq: {method: 'INVITE', seq: 1},
'content-type': 'application/sdp',
contact: [{uri: `sip:probe@${config.sip_ip}:${config.sip_port}`}],
'Privacy': 'id',
},
content:
'v=0\r\n'+
`o=- 13374 13374 IN IP4 ${config.sip_ip}\r\n`+
's=-\r\n'+
`c=IN IP4 ${config.sip_ip}\r\n`+
't=0 0\r\n'+
'm=audio 8888 RTP/AVP 0 8\r\n'+
'a=rtpmap:0 PCMU/8000\r\n'+
'a=rtpmap:8 PCMA/8000\r\n'+
'a=sendrecv\r\n'
},
function(rs) {
//console.log(rs)
if(rs.status >= 300) {
console.log(`${ref} call failed. status=${rs.status}. reason=${rs.headers['reason']}`)
} else if(rs.status == 180 || rs.status == 183) {
console.log(`${ref} call got status=${rs.status}`)
var params = {
method: 'CANCEL',
uri: uri,
headers: {
via: rs.headers['via'],
to: rs.headers['to'],
from: rs.headers['from'],
'call-id': rs.headers['call-id'],
cseq: {method: 'CANCEL', seq: 1},
}
}
if(rs.headers['record-route']) {
params.headers['route'] = rs.headers['record-route']
}
//console.log(params)
sip.send(params, function(rs) {
console.log(`${ref} call CANCEL got status=${rs.status}`)
})
} else if(rs.status < 200) {
console.log(`${ref} Provisional. status=${rs.status}`)
} else {
console.log(`${ref} call answer. status=${rs.status}`)
// yes we can get multiple 2xx response with different tags
var headers = {
to: rs.headers.to,
from: rs.headers.from,
'call-id': rs.headers['call-id'],
cseq: {method: 'ACK', seq: rs.headers.cseq.seq},
}
if(rs.headers['record-route']) {
headers['route'] = rs.headers['record-route']
}
sip.send({
method: 'ACK',
uri: rs.headers.contact[0].uri,
headers: headers,
})
setTimeout(() => {
var headers = {
to: rs.headers.to,
from: rs.headers.from,
'call-id': rs.headers['call-id'],
cseq: {method: 'BYE', seq: 2},
via: []
}
if(rs.headers['record-route']) {
headers['route'] = rs.headers['record-route']
}
sip.send({
method: 'BYE',
uri: rs.headers.contact[0].uri,
headers: headers,
},
rs => {
console.log(`BYE got ${JSON.stringify(rs)}`)
})
}, 50)
}
}
)
}
var count = 0
var tid = null
var start = () => {
tid = setInterval(() => {
console.log(`+++++++++ count=${count} ++++++++++`)
make_call()
count++;
if(count > 1000000) {
clearInterval(tid)
count=0
console.log("Resting for a while")
setTimeout(() => {
start()
}, 120 * 1000)
}
}, 1)
}
start()

We start sipp UAS this way:

$ sipp -i 127.0.0.1 -p 5000 -sf uas_183_cancel_no_487_request_terminated.xml

Then we start the test with:

$ node mc.js sip:127.0.0.1:5000

Then we will see node memory usage increasing:

takeshi:sip_js_test$ ps -o pid,user,%mem,command ax|grep node
  12146 takeshi  3.4 node mc.js sip:127.0.0.1:5000
  12602 takeshi   0.0 grep node
takeshi:sip_js_test$ ps -o pid,user,%mem,command ax|grep node
  12146 takeshi  5.3 node mc.js sip:127.0.0.1:5000
  12604 takeshi   0.0 grep node
takeshi:sip_js_test$ ps -o pid,user,%mem,command ax|grep node
  12146 takeshi  12.0 node mc.js sip:127.0.0.1:5000
  12749 takeshi   0.0 grep node
takeshi:sip_js_test$ ps -o pid,user,%mem,command ax|grep node
  12146 takeshi  13.7 node mc.js sip:127.0.0.1:5000
  12902 takeshi   0.0 grep node

And evetually it will crash:

76e80f6e-55bd-4a5d-9a0e-1b8c15a7ddea call got status=183
7b2d547c-2746-41f5-a564-4170c70834b7 Provisional. status=100
76e80f6e-55bd-4a5d-9a0e-1b8c15a7ddea call CANCEL got status=200
7b2d547c-2746-41f5-a564-4170c70834b7 call got status=183

<--- Last few GCs --->

[12146:0x311ad60]   514797 ms: Mark-sweep 1996.3 (2070.7) -> 1983.0 (2066.5) MB, 3463.2 / 0.0 ms  (average mu = 0.192, current mu = 0.100) allocation failure scavenge might not succeed
[12146:0x311ad60]   518194 ms: Mark-sweep 1997.7 (2066.5) -> 1981.0 (2068.7) MB, 2932.7 / 0.0 ms  (average mu = 0.165, current mu = 0.137) allocation failure scavenge might not succeed


<--- JS stacktrace --->

==== JS stack trace =========================================

    0: ExitFrame [pc: 0x1409219]
Security context: 0x3d52334c08d1 <JSObject>
    1: open [0x194fe17a5091] [/mnt/ssd/work/src/git/brastel/sip_pstn_probe/node_modules/sip/sip.js:~840] [pc=0xd02bef0b395](this=0x194fe17a4021 <Object map = 0x104e2e260a59>,0x2aa1df127179 <Object map = 0x104e2e266729>,0x323d283259b1 <JSFunction (sfi = 0x3d7f9623d131)>)
    2: next [0x323d283258f9] [/mnt/ssd/work/src/git/brastel/sip_pstn_probe/node_modules/sip/si...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: 0xa17c40 node::Abort() [node]
 2: 0xa1804c node::OnFatalError(char const*, char const*) [node]
 3: 0xb95a7e v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node]
 4: 0xb95df9 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
 5: 0xd53075  [node]
 6: 0xd53706 v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [node]
 7: 0xd5ffc5 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [node]
 8: 0xd60e75 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
 9: 0xd6392c v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
10: 0xd2a34b v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationType, v8::internal::AllocationOrigin) [node]
11: 0x106c91e v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [node]
12: 0x1409219  [node]
Aborted (core dumped)
takeshi:sip_js_test$ 
takeshi:sip_js_test$ 
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<scenario name="simulated PSTN gateway">
<!-- start it this way -->
<!-- sipp -i 172.17.0.1 -p 5088 -sf uas.xml -->
<recv request="INVITE" crlf="true" >
</recv>
<send>
<![CDATA[
SIP/2.0 100 Trying
[last_To:];tag=[pid]SIPpTag01[call_number]
[last_From:]
[last_Call-ID:]
[last_CSeq:]
Contact: <sip:some-terminal@[local_ip]:[local_port]>
[last_Via:]
User-Agent: some-terminal
Content-Length: 0
]]>
</send>
<send>
<![CDATA[
SIP/2.0 183 Session Progress
[last_To:];tag=[pid]SIPpTag01[call_number]
[last_From:]
[last_Call-ID:]
[last_CSeq:]
Contact: sip:sipp@[local_ip]:[local_port]
[last_Record-Route:]
Supported: timer
Session-Expires: 21600; refresher=uas
[last_Via:]
User-Agent: sipp
Content-Type: application/sdp
Content-Length: [len]
v=0
o=sip 1220546354 1220546354 IN IP[local_ip_type] [local_ip]
s=SIP_Call
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 0 101
a=sendrecv
a=rtpmap:0 PCMU/8000
a=rtpmap:101 telephone-event/8000
]]>
</send>
<recv request="CANCEL"/>
<send>
<![CDATA[
SIP/2.0 200 OK
[last_To:]
[last_From:]
[last_Call-ID:]
[last_CSeq:]
[last_Via:]
User-Agent: sipp
Content-Length: 0
]]>
</send>
<label id="finished"/>
</scenario>
@MayamaTakeshi
Copy link
Author

Issue solved. See: kirm/sip.js#155

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment