why when exiting a Dart async Future is the following error not being caught (correctly)? - dart

I have a problem using Dart postgresql database driver (xxgreg on Github) insofar as when the postgresql server is not running and it needs to be, I am unable to correctly handle the error. I’ve attempted to solve this for a while now, so any help would be appreciated. I can easily work around it by handling it silently and simply testing if the database connection object is null, however I think it should be possible to handle the raising of an error. It should be noted that when the Postgresql server is running, there is no problem.
The error that I am getting is as follows :
“Uncaught Error: Exception: fConnectToDb: Database is not connected
Stack Trace: ………….”
The problem area relates to these lines of code : (Line 663 is called from line 169 below)
663 async.Future<bool> fConnectToDb(String sUri) {
664 async.Completer<bool> oCompleter = new async.Completer<bool>();
665
666 pg.connect(sUri)
667 .catchError((oError) {
668 String sErrorMsg = (oError is SocketException) ?
669 "Database is not connected"
670 : "Fatal error encountered ${oError}";
671 throw("fConnectToDb: ${sErrorMsg}");
//(expanded below)
I have previously encountered problems in this area where at line 671, instead of throwing an exception, I called an internal method which displayed an error, and terminated the program. I found however what appeared to be a problem doing that, and I found in that situation, throwing an error enabled the program to exit the Future method, and not doing that appeared to be the problem. The problem may relate to the Future not being completed, but I don’t know how to do that and also throw an exception.
The overall code in-question is as follows. I put a try at line 167… 406, however that doesn’t catch the error either.
164 /*
165 * Connect to database
166 */
167 try {
168 sCheckpoint = "Connect to Database";
169 fConnectToDb(sUri)
170 .catchError((oError) =>
171 fFatal(sCheckpoint, "Error = \n${oError}"))
172 .then((_) {
173 if (ogDb == null) // ogDb is global object for db connection
174 fFatal(sCheckpoint, "Database did not connect");
175
176 /*
177 * Perform an SQL Select to test connection
178 */
179 ogPrintLine.fPrintForce("Testing Db connection .....");
180 sCheckpoint = "test connection";
181 return fProcessSqlSelect ("SELECT count(*) FROM ${S_TABLE_NAME}",
182 false);
183 }).then((llResult) {
184
…………
…………
// (catch related to line 167)
406 } catch(oError) {fFatal("Program Main()",
407 "Checkpoint ${sCheckpoint}, Error = \n${oError}");}
408 }
………..
………..
660 /*
661 * Connect To Database
662 */
663 async.Future<bool> fConnectToDb(String sUri) {
664 async.Completer<bool> oCompleter = new async.Completer<bool>();
665
666 pg.connect(sUri)
667 .catchError((oError) {
668 String sErrorMsg = (oError is SocketException) ?
669 "Database is not connected"
670 : "Fatal error encountered ${oError}";
671 throw("fConnectToDb: ${sErrorMsg}");
672
673 }).then((pg.Connection oDb) {
674 ogDb = oDb;
675 oCompleter.complete(true);
676 return;
677
678 });
679
680 return oCompleter.future;
681 }

As far as I can determine, it appears to me that it's Ok to throw an error in a Future providing it's followed by a catchError() that doesn't throw an error.
The following code appears to solve the problem that I was having :
/*
* Connect To Database
*/
async.Future<bool> fConnectToDb(String sUri) {
async.Completer<bool> oCompleter = new async.Completer<bool>();
pg.connect(sUri).then((pg.Connection oDb) {
ogDb = oDb; // assign to global database object
oCompleter.complete(true);
return;
}).catchError((oError) =>
fFatal("fConnectToDb", "Error=\n${oError}"));
return oCompleter.future;
}

Related

Invalid Mutability Exception when using background threads in KMM project on iOS

I am working on a KMM project and am currently developing a model layer. In order to work with data I was planning to create a singleton like so:
#ThreadLocal object Repository {
private var dao: DataAccessObject? = null
private val scope = CoroutineScope(Dispatchers.Main)
fun injectDao(dao: DataAccessObject) {
scope.async {
Repository.dao = dao
}
}
suspend fun create(dataObjectType: TypeOfDataObject): DataObject? {
var dataObject: DataObject? = null
val job = scope.async {
dataObject = dao?.create(dataObjectType = dataObjectType)
}
job.await()
return dataObject
}
}
In such implementation as you see the request to the database is handled in Main thread, which's quite not good. But it works and the data is returned from the function correctly. The next obvious step is to try to run it in background scope. To make it we should just redeclare scope:
private val scope = CoroutineScope(Dispatchers.Default)
When we run the code and call create function from somewhere it falls with
Uncaught Kotlin exception: kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlin.native.internal.Ref#5761ad88
2021-02-02 23:54:50.408645+0300 Plendy[28960:2893398] [] nw_protocol_get_quic_image_block_invoke dlopen libquic failed
at 0 Shared 0x000000010d51640f kfun:kotlin.Throwable#<init>(kotlin.String?){} + 95 (/Users/teamcity/buildAgent/work/f01984a9f5203417/runtime/src/main/kotlin/kotlin/Throwable.kt:23:37)
at 1 Shared 0x000000010d50f0bd kfun:kotlin.Exception#<init>(kotlin.String?){} + 93 (/Users/teamcity/buildAgent/work/f01984a9f5203417/runtime/src/main/kotlin/kotlin/Exceptions.kt:23:44)
at 2 Shared 0x000000010d50f32d kfun:kotlin.RuntimeException#<init>(kotlin.String?){} + 93 (/Users/teamcity/buildAgent/work/f01984a9f5203417/runtime/src/main/kotlin/kotlin/Exceptions.kt:34:44)
at 3 Shared 0x000000010d5448cd kfun:kotlin.native.concurrent.InvalidMutabilityException#<init>(kotlin.String){} + 93 (/Users/teamcity/buildAgent/work/f01984a9f5203417/runtime/src/main/kotlin/kotlin/native/concurrent/Freezing.kt:22:60)
at 4 Shared 0x000000010d5460af ThrowInvalidMutabilityException + 431 (/Users/teamcity/buildAgent/work/f01984a9f5203417/runtime/src/main/kotlin/kotlin/native/concurrent/Internal.kt:92:11)
at 5 Shared 0x000000010d6470b0 MutationCheck + 128
at 6 Shared 0x000000010d5640f8 kfun:kotlin.native.internal.Ref#<set-element>(1:0){} + 104 (/Users/teamcity/buildAgent/work/f01984a9f5203417/runtime/src/main/kotlin/kotlin/native/internal/Ref.kt:12:5)
at 7 Shared 0x000000010d4a1d5b kfun:com.plendy.PlendyCore.Model.KNPlendyData.$create$lambda-1COROUTINE$4.invokeSuspend#internal + 779 (/Users/petr/Documents/Projects/Plendy/Android/Plendy/PlendyCore/src/commonMain/kotlin/com/plendy/PlendyCore/Model/KNPlendyData.kt:23:13)
at 8 Shared 0x000000010d537958 kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#resumeWith(kotlin.Result<kotlin.Any?>){} + 760 (/Users/teamcity/buildAgent/work/f01984a9f5203417/runtime/src/main/kotlin/kotlin/coroutines/ContinuationImpl.kt:30:39)
at 9 Shared 0x000000010d6d7a78 kfun:kotlinx.coroutines.DispatchedTask#run(){} + 2680 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/internal/DispatchedTask.kt:106:71)
at 10 Shared 0x000000010d687fb8 kfun:kotlinx.coroutines.EventLoopImplBase#processNextEvent(){}kotlin.Long + 840 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/EventLoop.common.kt:274:18)
at 11 Shared 0x000000010d6efbbb kfun:kotlinx.coroutines#runEventLoop(kotlinx.coroutines.EventLoop?;kotlin.Function0<kotlin.Boolean>){} + 843 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/Builders.kt:80:40)
at 12 Shared 0x000000010d6f8d39 kfun:kotlinx.coroutines.WorkerCoroutineDispatcherImpl.start$lambda-0#internal + 409 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/Workers.kt:49:17)
at 13 Shared 0x000000010d6f8f30 kfun:kotlinx.coroutines.WorkerCoroutineDispatcherImpl.$start$lambda-0$FUNCTION_REFERENCE$35.invoke#internal + 64 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/Workers.kt:47:24)
at 14 Shared 0x000000010d6f8f90 kfun:kotlinx.coroutines.WorkerCoroutineDispatcherImpl.$start$lambda-0$FUNCTION_REFERENCE$35.$<bridge-UNN>invoke(){}#internal + 64 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/Workers.kt:47:24)
at 15 Shared 0x000000010d545d59 WorkerLaunchpad + 185 (/Users/teamcity/buildAgent/work/f01984a9f5203417/runtime/src/main/kotlin/kotlin/native/concurrent/Internal.kt:69:54)
at 16 Shared 0x000000010d64ba4f _ZN6Worker19processQueueElementEb + 3135
at 17 Shared 0x000000010d64adf6 _ZN12_GLOBAL__N_113workerRoutineEPv + 54
at 18 libsystem_pthread.dylib 0x0000000110a86950 _pthread_start + 224
at 19 libsystem_pthread.dylib 0x0000000110a8247b thread_start + 15
What is strange that the data is written to the db, meaning that dao is called successfully, but data isn't returning from the function, because the exception occurs earlier. At this point I don't understand to what frozen object does the exception relates? What I've tried next is to remove job.await() line and it worked perfectly with no exceptions besides of cause having null in function's output.
So my question is: how to make code run in a background thread still having an ability to wait for its output?
You should include more of the exception info to help figure out what's happening, and you can use ensureNeverFrozen to help identify when something is being inadvertently frozen. However, in this case, I think I can figure it out.
In this case, capturing a reference to dataObject in your background lambda will freeze it. Trying to reassign it is (probably) throwing your exception.
var dataObject: DataObject? = null
val job = scope.async {
//Trying to assign the frozen dataObject will fail
dataObject = dao?.create(dataObjectType = dataObjectType)
}
Since you're already in a suspend function, why not just use something like withContext?
suspend fun create(dataObjectType: TypeOfDataObject): DataObject? {
val dataObject = withContext(Dispatchers.Default) {
dao?.create(dataObjectType = dataObjectType)
}
return dataObject
}
And if you're going that far ...
suspend fun create(dataObjectType: TypeOfDataObject): DataObject? = withContext(Dispatchers.Default) {
dao?.create(dataObjectType = dataObjectType)
}

Parse SDK for iOS throw exception Attempted to find non-existent uuid while call pin

I'm using parse for iOS version 1.6 through cocoapods.
When I call the function pin for a PFObject the function throw the exception:
NSInternalInconsistencyException => Attempted to find non-existent uuid 085CC82A-3093-4F48-8576-382C1B0EC02B
the code looks like this:
[PFQuery queryWithClassName:#"Product"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (Product* obj in objects) {
[self.allProducts addObject:obj];
#try {
[obj pin];
}
#catch (NSException *exception) {
NSLog(#"Log => %#", exception);
}
}
}
}];
The app shows this in the console:
2014-12-17 20:38:01.116 Nobly Dev[478:57860] Exception => Attempted to find non-existent uuid 085CC82A-3093-4F48-8576-382C1B0EC02B
Previously I enable the local datastore with the call to [Parse enableLocalDatastore] and I cam correctly store other objects in the local datastore.
I'm running the application in an iPad 3 with iOS 8.1
I found this other question com.parse.ParseException: java.lang.IllegalStateException: Attempted to find non-existent uuid but without answers...
Any ideas?
PS: this is part of the report from crashlytics
Fatal Exception: NSInternalInconsistencyException
Attempted to find non-existent uuid 085CC82A-3093-4F48-8576-382C1B0EC02B
>>> PFOfflineStore.m line 944
__52-[PFOfflineStore _getPointerAsyncWithUUID:database:]_block_invoke
BFTask.m line 335
__48-[BFTask continueWithExecutor:withSuccessBlock:]_block_invoke
BFTask.m line 287
__41-[BFTask continueWithExecutor:withBlock:]_block_invoke_2
BFExecutor.m line 43
__29+[BFExecutor defaultExecutor]_block_invoke_2
BFExecutor.m line 107
-[BFExecutor execute:]
BFTask.m line 284
__41-[BFTask continueWithExecutor:withBlock:]_block_invoke
BFTask.m line 319
-[BFTask continueWithExecutor:withBlock:]
BFTask.m line 331
-[BFTask continueWithExecutor:withSuccessBlock:]
BFTask.m line 341
-[BFTask continueWithSuccessBlock:]
PFOfflineStore.m line 939
-[PFOfflineStore _getPointerAsyncWithUUID:database:]
PFOfflineStore.m line 282
__51-[PFOfflineStore fetchObjectLocallyAsync:database:]_block_invoke_2
PFInternalUtils.m line 725
+[PFInternalUtils traverseObject:usingBlock:seenObjects:]
PFInternalUtils.m line 705
__57+[PFInternalUtils traverseObject:usingBlock:seenObjects:]_block_invoke
16
CoreFoundation
__NSArrayEnumerate + 386
17
CoreFoundation
-[NSArray enumerateObjectsWithOptions:usingBlock:] + 62
PFInternalUtils.m line 704
+[PFInternalUtils traverseObject:usingBlock:seenObjects:]
PFInternalUtils.m line 719
+[PFInternalUtils traverseObject:usingBlock:seenObjects:]
PFInternalUtils.m line 705
This is a known bug in Parse.com API version 1.6. They have currently reproduced it in-house and are working on a solution. (According to their user forums, they are aware of the problem as of 2014/12/15.) For now, your best bet it wait before using the iOS localDataStore.
For more info, see the bug report here:
https://developers.facebook.com/bugs/614018488703097/

Remote Connection like Browser Toolbox

I'm trying to interact with another open profile, which is a seperate process. Browser Toolbox does this. I was wondering how can I re-simulate this behavior? Without the prompt asking for "allow remote connection"?
My goal is to (1) find all open firefox process, (2) access each of its xpcom and figure out the profile name, (3) and if its a profile name Im interested in, Ill focus its most recent window.
I don't know but I'm getting somewhere by tracing it in MXR:
http://mxr.mozilla.org/mozilla-release/source/browser/devtools/framework/toolbox-process-window.js#11
11 let { debuggerSocketConnect, DebuggerClient } =
12 Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {});
13 let { ViewHelpers } =
14 Cu.import("resource:///modules/devtools/ViewHelpers.jsm", {});
15
16 /**
17 * Shortcuts for accessing various debugger preferences.
18 */
19 let Prefs = new ViewHelpers.Prefs("devtools.debugger", {
20 chromeDebuggingHost: ["Char", "chrome-debugging-host"],
21 chromeDebuggingPort: ["Int", "chrome-debugging-port"]
22 });
23
24 let gToolbox, gClient;
25
26 function connect() {
27 window.removeEventListener("load", connect);
28 // Initiate the connection
29 let transport = debuggerSocketConnect(
30 Prefs.chromeDebuggingHost,
31 Prefs.chromeDebuggingPort
32 );
33 gClient = new DebuggerClient(transport);
34 gClient.connect(() => {
35 let addonID = getParameterByName("addonID");
36
37 if (addonID) {
38 gClient.listAddons(({addons}) => {
39 let addonActor = addons.filter(addon => addon.id === addonID).pop();
40 openToolbox({ addonActor: addonActor.actor, title: addonActor.name });
41 });
42 } else {
43 gClient.listTabs(openToolbox);
44 }
45 });
46 }
47
I ran the profile and it looks like the pref ..-host is localhost and ..-port is 6080. I'm not sure how this helps target a specific profile though. Maybe on start of the browser toolbox it opened port 6080 to the opener profile. I'm not sure, but if its true, then you'll have to run code from within the target profile to open a port maybe.
Totally not sure though.
But port is opened here:
http://mxr.mozilla.org/mozilla-release/source/browser/devtools/framework/ToolboxProcess.jsm#107
106
107 BrowserToolboxProcess.prototype = {
108 /**
109 * Initializes the debugger server.
110 */
111 _initServer: function() {
112 dumpn("Initializing the chrome toolbox server.");
113
114 if (!this.loader) {
115 // Create a separate loader instance, so that we can be sure to receive a
116 // separate instance of the DebuggingServer from the rest of the devtools.
117 // This allows us to safely use the tools against even the actors and
118 // DebuggingServer itself, especially since we can mark this loader as
119 // invisible to the debugger (unlike the usual loader settings).
120 this.loader = new DevToolsLoader();
121 this.loader.invisibleToDebugger = true;
122 this.loader.main("devtools/server/main");
123 this.debuggerServer = this.loader.DebuggerServer;
124 dumpn("Created a separate loader instance for the DebuggerServer.");
125
126 // Forward interesting events.
127 this.debuggerServer.on("connectionchange", this.emit.bind(this));
128 }
129
130 if (!this.debuggerServer.initialized) {
131 this.debuggerServer.init();
132 this.debuggerServer.addBrowserActors();
133 dumpn("initialized and added the browser actors for the DebuggerServer.");
134 }
135
136 this.debuggerServer.openListener(Prefs.chromeDebuggingPort);
137
138 dumpn("Finished initializing the chrome toolbox server.");
139 dumpn("Started listening on port: " + Prefs.chromeDebuggingPort);
140 },
141

I cannot catch the "No space left on device" exception when using NSFileHandle writedata function

I used NSFileHandle to writedata to a file.
NSFilehandle *handle = [NSFileHandle fileHandleForWritingAtPath:#"path/of/file"];
#try {
[handle writedata:data];
} #catch (NSException *e) {
// when exception occur, never got here
NSLog(#"%#", e);
}
As my device disk space is full, calling writedata will fail. But I can't catch the exception.
My program log info:
2014-05-23 16:17:24.435 mytest[12919:3203] An uncaught exception was raised
2014-05-23 16:17:24.435 mytest[12919:3203] *** -[NSConcreteFileHandle writeData:]:
No space left on device
2014-05-23 16:17:24.436 mytest[12919:3203] (
0 CoreFoundation 0x00007fff8fae725c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff8cbb3e75 objc_exception_throw + 43
2 CoreFoundation 0x00007fff8fae710c +[NSException raise:format:] + 204
3 Foundation 0x00007fff93640f31 __34-[NSConcreteFileHandle writeData:]_block_invoke + 84
4 Foundation 0x00007fff93840020 __49-[_NSDispatchData enumerateByteRangesUsingBlock:]_block_invoke + 32
5 libdispatch.dylib 0x00007fff8bfc2fad _dispatch_client_callout3 + 9
6 libdispatch.dylib 0x00007fff8bfc2f28 _dispatch_data_apply + 113
7 libdispatch.dylib 0x00007fff8bfc9502 dispatch_data_apply + 31
8 Foundation 0x00007fff9383fff9 -[_NSDispatchData enumerateByteRangesUsingBlock:] + 83
9 Foundation 0x00007fff93640ed2 -[NSConcreteFileHandle writeData:] + 150
10 ZiSyncMac 0x000000010000b1eb -[TransferFile writePart:data:] + 475
I found out writedata calls a dispatch to do real write data to the file system. So I think writedata will throw a exception in GCD.
How can I handle the GCD exception in my code?
From a website that's been hijacked since (not providing the link for that reason, but the explanation is still useful):
seekToEndOfFile() and writeData() are not marked as throws (they don’t
throw an NSError object which can be caught in with a do-try-catch
block), which means in the current state of Swift, the NSExceptions
raised by them cannot be “caught”.
If you’re working on a Swift project, you could create an Objective-C
class which implements your NSFileHandle methods that catches the
NSExceptions (like in this question), but otherwise you’re out of
luck.
What #eric said is right.
But, what you can do is check before that you write for how much space is left in the disk and only after it write to the disk.

why is code not executing on return from Future in Dart program

Could someone please explain to me why in the following code (using r25630 Windows), the value of iInsertTot at line 241 is null, or more to the point, why is line 234 ("return iInsertTot;") not executed and therefore at line 241, iInsertTot is null. The value of iInsertTot at lines 231/232 is an integer. While I can and probably should code this differently, I thought that I would try and see if it worked, because my understanding of Futures and Chaining was that it would work. I have used “return” in a similar way before and it worked, but I was returning null in those cases (eg. line 201 below).
/// The problem lines are :
233 fUpdateTotalsTable().then((_) {
234 return iInsertTot;
235 });
While running in the debugger, it appears that line 234 “return iInsertTot;” is never actually executed. Running from command line has the same result.
The method being called on line 233 (fUpdateTotalsTable) is something I am just in the process of adding, and it consists basically of sync code at this stage. However, the debugger appears to go through it correctly.
I have included the method “fUpdateTotalsTable()” (line 1076) just in case that is causing a problem.
Lines 236 to 245 have just been added, however just in case that code is invalid I have commented those lines out and run with the same problem occurring.
218 /*
219 * Process Inserts
220 */
221 }).then((_) {
222 sCheckpoint = "fProcessMainInserts";
223 ogPrintLine.fPrintForce ("Processing database ......");
224 int iMaxInserts = int.parse(lsInput[I_MAX_INSERTS]);
225 print ("");
226 return fProcessMainInserts(iMaxInserts, oStopwatch);
227 /*
228 * Update the 'totals' table with the value of Inserts
229 */
230 }).then((int iReturnVal) {
231 int iInsertTot = iReturnVal;
232 sCheckpoint = "fUpdateTotalsTable (insert value)";
233 fUpdateTotalsTable().then((_) {
234 return iInsertTot;
235 });
236 /*
237 * Display totals for inserts
238 */
239 }).then((int iInsertTot) {
240 ogTotals.fPrintTotals(
241 "${iInsertTot} rows inserted - Inserts completed",
242 iInsertTot, oStopwatch.elapsedMilliseconds);
243
244 return null;
245 /*
192 /*
193 * Clear main table if selected
194 */
195 }).then((tReturnVal) {
196 if (tReturnVal)
197 ogPrintLine.fPrintForce("Random Keys Cleared");
198 sCheckpoint = "Clear Table ${S_TABLE_NAME}";
199 bool tClearTable = (lsInput[I_CLEAR_YN] == "y");
200 if (!tFirstInstance)
201 return null;
202 return fClearTable(tClearTable, S_TABLE_NAME);
203
204 /*
205 * Update control row to increment count of instances started
206 */
207 }).then((_) {
1073 /*
1074 * Update totals table with values from inserts and updates
1075 */
1076 async.Future<bool> fUpdateTotalsTable() {
1077 async.Completer<bool> oCompleter = new async.Completer<bool>();
1078
1079 String sCcyValue = ogCcy.fCcyIntToString(ogTotals.iTotAmt);
1080
1081 print ("\n********* Total = ${sCcyValue} \n");
1082
1083 oCompleter.complete(true);
1084 return oCompleter.future;
1085 }
Your function L230-235 does not return anything and that's why your iInsertTot is null L239. To make it work you have to add a return at line 233.
231 int iInsertTot = iReturnVal;
232 sCheckpoint = "fUpdateTotalsTable (insert value)";
233 return fUpdateTotalsTable().then((_) {
234 return iInsertTot;
235 });

Resources