WebRtc Native-Crashed when I call peerconnection->Close() - webrtc

How to close or destruct a PeerConnectionInterface object? It crashed when I'm trying to do so.
I have an object declared like this:
rtc::scoped_refptr<webrtc::PeerConnectionInterface> _peerConnection;
It works fine after I create the PeerConnectionInterface by factory.
However, when the session is over and I try to call _peerConnection->Close(); The program crashed.
And I also try to call _peerConnection.release()->Release(); Crashed as well.
I print logs in PeerConnection.cc which is from the source code of WebRtc, and find that it crashed here, which is in Close() function and ~PeerConnection() function:
webrtc_session_desc_factory_.reset(); //PeerConnection.cc
The declare is
std::unique_ptr<WebRtcSessionDescriptionFactory> webrtc_session_desc_factory_;
So I continue to log in WebRtcSessionDescriptionFactory.cc, the ~WebRtcSessionDescriptionFactory() function. Crashed in this function:FailPendingRequests().
Entered the FailPendingRequests() function:
RTC_DCHECK(signaling_thread_->IsCurrent());
while (!create_session_description_requests_.empty()) {
const CreateSessionDescriptionRequest& request =
create_session_description_requests_.front();
//Crashed here in third or fourth loop
PostCreateSessionDescriptionFailed(request.observer,
((request.type == CreateSessionDescriptionRequest::kOffer) ?
"CreateOffer" : "CreateAnswer") + reason);
create_session_description_requests_.pop();
}
I will be really grateful for any suggestion!

I faced the same issue in iOS when implemented Kurento Library. The key to fix this issue is to dispose the resources in the right manner.
Steps I followed:
The order of creation:
Created WebRTCPeer object
Created RoomClient object
Once RoomClient connected, generated SDP Offer.
and so on.
The order of disposition:
Disconnected RoomClient first.
Kept an eye on "RTCIceConnectionState", "RTCIceGatheringState" in the WebRTC events.
Once "RTCIceConnectionState" is closed and iceGatheringState is "RTCIceGatheringStateComplete", then disposed WebRTCPeer object.
This way the problem got resolved, otherwise resources were initialised and main object were disposed, which results in crashes.
Hope that helps!

Related

BLE kotlin .discoverServices() doesn't find any service

I implemented two different solution to discover service on my BLE device. One use a handler then return what .discoverService have found, the other one is really similar but give the size of the service discovered list that is always 0. I tried it with my realme buds 2 as test and some other device publically visible. The result is always 0. What can the problem be?
Handler(Looper.getMainLooper()).post {
var temp = bluetoothGatt?.discoverServices()
addGlog("discordservice() returned ${temp.toString()}")
}
addGlog("handler discover service reached an end")
val gattServices: List<BluetoothGattService> = gatt.getServices()
addGlog("Services count: " + gattServices.size)
for (gattService in gattServices) {
val serviceUUID = gattService.uuid.toString()
addGlog("Service uuid $serviceUUID")
}
edit: AddGlog is a simple log function to print results
answer: The code is not wrong but it take some time to discover those services so i put this code in a button. In this way there is 3-4 second of time between connecting with the device and make a discoveryservice operation. So a button make the conneting operations and another one the service discovery operations. I am sorry if my answer is pretty lame but I am still a noob on this topic

Kafka streams: groupByKey and reduce not triggering action exactly once when error occurs in stream

I have a simple Kafka streams scenario where I am doing a groupyByKey then reduce and then an action. There could be duplicate events in the source topic hence the groupyByKey and reduce
The action could error and in that case, I need the streams app to reprocess that event. In the example below I'm always throwing an error to demonstrate the point.
It is very important that the action only ever happens once and at least once.
The problem I'm finding is that when the streams app reprocesses the event, the reduce function is being called and as it returns null the action doesn't get recalled.
As only one event is produced to the source topic TOPIC_NAME I would expect the reduce to not have any values and skip down to the mapValues.
val topologyBuilder = StreamsBuilder()
topologyBuilder.stream(
TOPIC_NAME,
Consumed.with(Serdes.String(), EventSerde())
)
.groupByKey(Grouped.with(Serdes.String(), EventSerde()))
.reduce { current, _ ->
println("reduce hit")
null
}
.mapValues { _, v ->
println(Id: "${v.correlationId}")
throw Exception("simulate error")
}
To cause the issue I run the streams app twice. This is the output:
First run
Id: 90e6aefb-8763-4861-8d82-1304a6b5654e
11:10:52.320 [test-app-dcea4eb1-a58f-4a30-905f-46dad446b31e-StreamThread-1] ERROR org.apache.kafka.streams.KafkaStreams - stream-client [test-app-dcea4eb1-a58f-4a30-905f-46dad446b31e] All stream threads have died. The instance will be in error state and should be closed.
Second run
reduce hit
As you can see the .mapValues doesn't get called on the second run even though it errored on the first run causing the streams app to reprocess the same event again.
Is it possible to be able to have a streams app re-process an event with a reduced step where it's treating the event like it's never seen before? - Or is there a better approach to how I'm doing this?
I was missing a property setting for the streams app.
props["processing.guarantee"]= "exactly_once"
By setting this, it will guarantee that any state created from the point of picking up the event will rollback in case of a exception being thrown and the streams app crashing.
The problem was that the streams app would pick up the event again to re-process but the reducer step had state which has persisted. By enabling the exactly_once setting it ensures that the reducer state is also rolled back.
It now successfully re-processes the event as if it had never seen it before

Unhandled rejection Error: Chrome still being created

When I use { insertDefaultUI: false } to create a video I get an "Unhandled rejection Error: Chrome still being created" when trying to cleanup after I'm done with session.disconnect().
Any ideas...?
I'm on the TokBox dev team.
The error is not something you should be concerned with, it's something internal to the SDK.
The bug is that the error is appearing at all. I have created a bug report and this error should disappear in a future release. Until then you can safely ignore it.
Thanks for the report.
I'm having the very same problem when trying to unpublish my publisher
Could you guys provide a solution?
Unhandled rejection Error: Chrome still being created
at Object.chromeMixin.reset (https://static.opentok.com/v2/js/opentok.js:41755:16)
at reset (https://static.opentok.com/v2/js/opentok.js:42837:19)
at Publisher.destroy (https://static.opentok.com/v2/js/opentok.js:43211:7)
at defaultAction (https://static.opentok.com/v2/js/opentok.js:43524:20)
at executeDefaultAction (https://static.opentok.com/v2/js/opentok.js:25584:19)
at Object.api.dispatchEvent (https://static.opentok.com/v2/js/opentok.js:25735:7)
at Publisher.self.dispatchEvent (https://static.opentok.com/v2/js/opentok.js:25427:19)
at Object.streamDestroyed (https://static.opentok.com/v2/js/opentok.js:43527:16)
at Object.unpublishFromSession (https://static.opentok.com/v2/js/opentok.js:43507:16)
at Session.unpublish (https://static.opentok.com/v2/js/opentok.js:47031:19)
at Object.me.stop (https://x/rt.js:498:17)
at b.$scope.callBreak (https://x/ler.js:16:24)
at fn (eval at compile (https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js:239:266), <anonymous>:4:165)
From previous event:
at createChromeMixin (https://static.opentok.com/v2/js/opentok.js:41672:21)
at new Publisher (https://static.opentok.com/v2/js/opentok.js:42826:23)
at Object.initPublisher (https://static.opentok.com/v2/js/opentok.js:44275:21)
at Object.me.start (https://x/rt.js:457:27)
at b.$scope.start (https://x/ler.js:6:24)
at fn (eval at compile (https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js:239:266), <anonymous>:4:161)
at e (https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js:284:187)
at b.$eval (https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js:148:347)
at b.$apply (https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js:149:52)
at HTMLButtonElement.<anonymous> (https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js:284:239)
at HTMLButtonElement.dispatch (https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js:4:8549)
at HTMLButtonElement.r.handle (https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js:4:5252)
I might be a bit late, but I'll share my findings. When using a custom UI on your publisher, use the following event:
publisher.on('streamDestroyed',function(event){ event.preventDefault();});
This disallows opentok calling widget destroying events which causes the exception related to this question, however now I don't know how to stop the stream lol, since if I call event.target.destroy() will generate the same exception, lol ... so I'm trying to figure that out.

What's the best way to get HTable handle of HBase?

One way is directly call the HTable constructor, another is to call the getTable method from a HConnection. The second option requires the HConnection to be "unmanaged", which is not very good for me because my process will have many threads accessing HBase. I don't want to re-invent the wheel to manage the HConnections on my own.
Thanks for your help.
[Updates]:
We are stuck with 0.98.6, so ConnectionFactory is not available.
I found the bellow jira suggesting to create an "unmanaged" connection and use a single ExecuteService to create HTable. Why can't we simply use the getTable method of the unmanaged connection to get HTable? Is that because of HTable is not thread safe?
https://issues.apache.org/jira/browse/HBASE-7463
Im stuck with old versions (<0.94.11) in which you can still use HTablePool but since it has been deprecated by HBASE-6580 I think requests from HTables to the RS are now automatically pooled by providing an ExecutorService:
ExecutorService executor = Executors.newFixedThreadPool(10);
Connection connection = ConnectionFactory.createConnection(conf, executor);
Table table = connection.getTable(TableName.valueOf("mytable"));
try {
table.get(...);
...
} finally {
table.close();
connection.close();
}
I've been unable to find any good examples/docs about it, so please notice this is untested code which may not work as expected.
For more information you can take a look to the ConnectionFactory documentation & to the JIRA issue:
https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/client/ConnectionFactory.html
https://issues.apache.org/jira/browse/HBASE-6580
Update, since you're using 0.98.6 and ConnectionFactory is not available you can use HConnectionManager instead:
HConnection connection = HConnectionManager.createConnection(config); // You can also provide an ExecutorService if you want to override the default one. HConnection is thread safe.
HTableInterface table = connection.getTable("table1");
try {
// Use the table as needed, for a single operation and a single thread
} finally {
table.close();
connection.close();
}
HTable is not thread safe so you must make sure you always get a new instance (it's a lightweight process) with HTableInterface table = connection.getTable("table1") and close it afterwards with table.close().
The flow would be:
Start your process
Initialize your HConnection
Each thread:
3.1 Gets a table from your HConnection
3.2 Writes/reads from the table
3.3 Closes the table
Close your HConnection when your process ends
HConnectionManager: http://archive.cloudera.com/cdh5/cdh/5/hbase/apidocs/org/apache/hadoop/hbase/client/HConnectionManager.html#createConnection(org.apache.hadoop.conf.Configuration)
HTable: http://archive.cloudera.com/cdh5/cdh/5/hbase/apidocs/org/apache/hadoop/hbase/client/HTable.html

Troubleshooting WebRTC code

I'm pulling my hair out with this one. A month or so ago, I was able to put together a proof-of-concept WebRTC demo, using some sample code from the good folks at SignalR. The demo is located here, the source for it is here, and it does what it's supposed to do.
But when I took that code and moved it into our actual application, I haven't been able to get it to work. Of course the code had to be changed significantly - different backends, different set of frameworks and supporting code, supporting multiple simultaneous connections, that sort of thing - but the core logic is very similar. But I can't get it to work.
I've put together a sample app here that demonstrates the problem:
https://bitbucket.org/smithkl42/signalr.webrtc
The core WebRTC logic is all in this TypeScript file:
https://bitbucket.org/smithkl42/signalr.webrtc/src/tip/SignalR.WebRTC/Scripts/Media/WebRTC.ts?at=default
It's several hundred lines long, so I won't bother posting it here, but you can see it by clicking on the link above.
When it runs, it produces output like this:
12:17:58.531 WebRTCController.call(): Calling 7d9e0d39-5047-4afe-86e5-e6e01b9f5955 when preparations have finished
12:17:58.533 WebRTCController.prepareForCall(): Preparing for call: localSessionId='39d2df53-6854-415a-8748-b5230eda2eb1'; remoteSessionId='7d9e0d39-5047-4afe-86e5-e6e01b9f5955'
12:18:0.139 Object.(): The user has granted media device access, so proceeding to prepare for call
12:18:0.141 Connection.createPeerConnection(): Creating peer connection; using stunServer stun:stun1.l.google.com:19302
12:18:0.144 (): Preparations finished. Creating and sending JSEP offer. Util.js:21
12:18:0.272 Connection.handleIceCandidate(): STUN server has found an ICE candidate (event.type='icecandidate').
12:18:0.282 Connection.handleIceCandidate(): STUN server has found an ICE candidate (event.type='icecandidate').
(More like that)
12:18:0.655 WebRTCController.handleJsepAnswer(): Handling JsepAnswer from 7d9e0d39-5047-4afe-86e5-e6e01b9f5955
12:18:0.694 Object.(): Sending ICE candidate to the remote machine: {"sdpMLineIndex":0,"sdpMid":"audio","candidate":"a=candidate:2999745851 1 udp 2113937151 192.168.56.1 62978 typ host generation 0\r\n"}
12:18:0.706 Object.(): Sending ICE candidate to the remote machine: {"sdpMLineIndex":0,"sdpMid":"audio","candidate":"a=candidate:2999745851 2 udp 2113937151 192.168.56.1 62978 typ host generation 0\r\n"}
(More like that)
But then it never connects, i.e., the video from the other side never starts playing. At the signaling layer, I can tell by the logs and by stepping through the code that the first browser is sending a JSEP offer; the second browser is receiving it, storing it and sending back an appropriate JSEP answer; and the first machine is storing that answer. Each peerConnection is then finding the ICE candidates and sending them to the remote machine; and each peerConnection is receiving and apparently trying those ICE candidates; and the peerConnections are even raising the onaddstream event. But the video never starts playing.
The state of the peerConnection object all the way through looks like this:
(iceGatheringState=new; iceState=starting; readyState=active)
The frustrating bit is that every so often, maybe one time out of 20, it does work, i.e., both videos show up. So I'm not doing everything wrong. It sounds like a timing issue of some sort - but I can't figure out what it is. And so far as I can tell, there's not much in the WebRTC objects (specifically RTCPeerConnection) to tell you what's going wrong.
I hate to ask anybody else to do my troubleshooting for me, but... well, I'm running out of options. Does anybody else see anything I'm doing obviously wrong?
Update 2012-12-19: I'm making some progress. I realized I was calling peerConnection.setLocalDescription() synchronously, i.e., without specifying callbacks. So now I've got some lines of code that look like this:
// Answer the call by sending a JsepAnswer message.
connection.peerConnection.createAnswer(
answer => {
connection.peerConnection.setLocalDescription(answer, () => {
var signalState: mData.SignalState = {
FromSessionId: connection.localSessionId,
ToSessionId: connection.remoteSessionId,
Message: JSON.stringify(answer)
};
me.roomHub.server.jsepAnswer(signalState);
mUtil.log("Sent JSEP answer: " + signalState.Message);
connection.readyForIceCandidates.resolve();
},
error => {
mUtil.error("Error setting local description from created answer: " + error + "; answer=" + JSON.stringify(answer));
});
},
error => {
mUtil.error("Error creating answer: " + error);
}, me.mediaConstraints);
And the setLocalDescription() error callback is showing this error:
16:14:42.439 WebRTCController.handleJsepOffer(): Error setting local description from created answer: SetLocalDescription failed.; answer={"sdp":"v=0\r\no=- 439659381 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf\r\nm=audio 1 RTP/SAVPF 103 104 111 0 8 107 106 105 13 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:vOKflTJ56gV0R9i0\r\na=ice-pwd:9nuXPMDvQ2mZATFCQyEzPRQz\r\na=sendrecv\r\na=mid:audio\r\na=rtcp-mux\r\na=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:m9q9pmLgLuFnfFC09KXKW5p8TjsKk+VdqX0OWv77\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:111 opus/48000/2\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:107 CN/48000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:126 telephone-event/8000\r\na=ssrc:548068416 cname:IXg8QRisWrd7+7f8\r\na=ssrc:548068416 msid:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf a0\r\na=ssrc:548068416 mslabel:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf\r\na=ssrc:548068416 label:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjfa0\r\nm=video 1 RTP/SAVPF 100 116 117\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:vOKflTJ56gV0R9i0\r\na=ice-pwd:9nuXPMDvQ2mZATFCQyEzPRQz\r\na=sendrecv\r\na=mid:video\r\na=rtcp-mux\r\na=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:m9q9pmLgLuFnfFC09KXKW5p8TjsKk+VdqX0OWv77\r\na=rtpmap:100 VP8/90000\r\na=rtpmap:116 red/90000\r\na=rtpmap:117 ulpfec/90000\r\na=ssrc:1460425980 cname:IXg8QRisWrd7+7f8\r\na=ssrc:1460425980 msid:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf v0\r\na=ssrc:1460425980 mslabel:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf\r\na=ssrc:1460425980 label:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjfv0\r\n","type":"answer"}
Now I just need to figure out why that particular SDP - which comes straight from the createAnswer() method - is failing.
Update 2012-12-20: I've created an online demonstration of the problem here: http://srdemo.alanta.com/. I've also turned on Chrome debug logging, with the result that I see a bunch of errors that look like this:
[6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null.
[6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null.
[6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null.
[6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null.
[6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null.
Not sure what relationship they have to my problem, but I'm continuing to look into it.
*Edit 2012-12-20: I've managed (I think) to narrow the problem down. See this question for more precise details.
Figured it out. Turns out that SignalR 1.0 RC1 has a bug in it that changes any "+" in a string into a space. So lines in the SDP that looked like this:
a=ice-pwd:qZFVvgfnSso1b8UV1SUDd2+z
Were getting changed into this:
a=ice-pwd:qZFVvgfnSso1b8UV1SUDd2 z
But because not every SDP had a "+" in it on a critical line, sometimes it would work. Everything explained.
The bug has been reported to the good folks working on SignalR (see https://github.com/SignalR/SignalR/issues/1194), and in the meantime, a simple encodeURIComponent() and decodeURIComponent() around the strings in question fixed it.