Is there a way for a RACSignal to keep receiving `next`s after an error? - ios

I'm trying to listen for both location updates and errors (through CLLocationManagerDelegate), and support the ability to track errors but filter them out of the final signal and keep it alive.
When I subscribe to the location signal (via ReactiveCocoaPlayground's -[LocationManager currentLocationSignal]), any errors received will end the signal.
I've tried -catch: and -catchTo: but those just catch one error and then end the signal.
I've tried returning a brand new instance of that signal inside -catch:, but then the error on THAT signal is uncaught (which causes a crash in a RAC() binding later on).
I've tried a recursive approach to that catch as well, which caused a stack overflow (maybe I just made a mistake though).
Is there a way to receive nexts after errors occur?

I believe you're looking for -[RACSignal retry]:
/// Resubscribes to the receiving signal if an error occurs.
- (RACSignal *)retry;

Related

WorkFusion RPAExpress Exception Handling

I'm using Error Handling in WorkFusion.
Is there a way to see the error message in the catch block i.e. exception occurred block.
How about using:
<log>exception_msg_var</log>
or
println exception_msg_var
exporting exceptions to datastore?
To get the error message in RPA Express, you can keep the code outside of exception handling and then, the software will through error message on its' own. Once you get the type of error (by running the bot once), you can put the solution in catch block by keeping the code inside exceptional handling feature.

ReactiveCocoa 4: How to send error to an observer without interrupting the signal

let (signal, sink) = Signal<[CLBeacon], BeaconManagerError>.pipe()
When I call this because the user disabled the Bluetooth:
sendError(self.sink, error)
the Signal is interrupted and I don't receive more next nor interrupted events after enabling the Bluetooth back again. The Signal is broken.
How can I send error types to the observer without interrupting / breaking the Signal? I can't find in the RAC 4 documentation. Thanks!
By design, an error causes the signal to finish. The documentation says:
failures should only be used to represent “abnormal” termination. If
it is important to let operators (or consumers) finish their work, a
Next event describing the result might be more appropriate.
If you want to turn errors into Next events, you can use flatMapError operator as described here or use retry if you want to allow only several occurances of the error.
If you want different semantics than Next* (Error|Completed) I recommend encoding that in the type. You can use a Signal that can't fail, but which values can be either success or failure, by using Result:
Signal<Result<[CLBeacon], BeaconManagerError>, NoError>
That signal will emit no errors, but its Next events will be Result.Success<[CLBeacon]> or Result.Failure<BeaconManagerError>, **and the signal won't terminate when receiving a Result.Failure.

Get error Thread 1 SIGABRT

I'm using CoreData in my app. Now add a new entry and try to save it. I don't know why but it fails with Thread 1: signal SIGABRT
This is my saving part:
var error: NSError? = nil
if !context.save(&error) {
abort()
}
It crashes in this line of code:
abort()
Does someone know why this happens and hoc I can solve it? I also use iCloud Sync if this could be a reason. Thanks a lot for your help!
Your code behaves exactly as intended. Google for "Unix abort".
NAME
abort - generate an abnormal process abort
SYNOPSIS
include
void abort(void);
DESCRIPTION
The abort() function causes abnormal process termination to occur, unless the signal SIGABRT is being caught and the signal handler does not return. The abnormal termination processing includes at least the effect of fclose() on all open streams, and message catalogue descriptors, and the default actions defined for SIGABRT. The SIGABRT signal is sent to the calling process as if by means of raise() with the argument SIGABRT.
The status made available to wait() or waitpid() by abort() will be that of a process terminated by the SIGABRT signal. The abort() function will override blocking or ignoring the SIGABRT signal.
RETURN VALUE
The abort() function does not return.
ERRORS
No errors are defined.
EXAMPLES
None.
APPLICATION USAGE
Catching the signal is intended to provide the application writer with a portable means to abort processing, free from possible interference from any implementation-provided library functions. If SIGABRT is neither caught nor ignored, and the current directory is writable, a core dump may be produced.
FUTURE DIRECTIONS
None.
SEE ALSO
exit(), kill(), raise(), signal(),
DERIVATION
Derived from Issue 1 of the SVID.

"EXC_BAD_ACCESS" vs "Segmentation fault". Are both same practically?

In my first few dummy apps(for practice while learning) I have come across a lot of EXC_BAD_ACCESS, that somehow taught me Bad-Access is : You are touching/Accessing a object that you shouldn't because either it is not allocated yet or deallocated or simply you are not authorized to access it.
Look at this sample code that has bad-access issue because I am trying to modify a const :
-(void)myStartMethod{
NSString *str = #"testing";
const char *charStr = [str UTF8String];
charStr[4] = '\0'; // bad access on this line.
NSLog(#"%s",charStr);
}
While Segmentation fault says : Segmentation fault is a specific kind of error caused by accessing memory that “does not belong to you.” It’s a helper mechanism that keeps you from corrupting the memory and introducing hard-to-debug memory bugs. Whenever you get a segfault you know you are doing something wrong with memory (more description here.
I wanna know two things.
One, Am I right about objective-C's EXC_BAD_ACCESS ? Do I get it right ?
Second, Are EXC_BAD_ACCESS and Segmentation fault same things and Apple has just improvised its name?
No, EXC_BAD_ACCESS is not the same as SIGSEGV.
EXC_BAD_ACCESS is a Mach exception (A combination of Mach and xnu compose the Mac OS X kernel), while SIGSEGV is a POSIX signal. When crashes occur with cause given as EXC_BAD_ACCESS, often the signal is reported in parentheses immediately after: For instance, EXC_BAD_ACCESS(SIGSEGV). However, there is one other POSIX signal that can be seen in conjunction with EXC_BAD_ACCESS: It is SIGBUS, reported as EXC_BAD_ACCESS(SIGBUS).
SIGSEGV is most often seen when reading from/writing to an address that is not at all mapped in the memory map, like the NULL pointer, or attempting to write to a read-only memory location (as in your example above). SIGBUS on the other hand can be seen even for addresses the process has legitimate access to. For instance, SIGBUS can smite a process that dares to load/store from/to an unaligned memory address with instructions that assume an aligned address, or a process that attempts to write to a page for which it has not the privilege level to do so.
Thus EXC_BAD_ACCESS can best be understood as the set of both SIGSEGV and SIGBUS, and refers to all ways of incorrectly accessing memory (whether because said memory does not exist, or does exist but is misaligned, privileged or whatnot), hence its name: exception – bad access.
To feast your eyes, here is the code, within the xnu-1504.15.3 (Mac OS X 10.6.8 build 10K459) kernel source code, file bsd/uxkern/ux_exception.c beginning at line 429, that translates EXC_BAD_ACCESS to either SIGSEGV or SIGBUS.
/*
* ux_exception translates a mach exception, code and subcode to
* a signal and u.u_code. Calls machine_exception (machine dependent)
* to attempt translation first.
*/
static
void ux_exception(
int exception,
mach_exception_code_t code,
mach_exception_subcode_t subcode,
int *ux_signal,
mach_exception_code_t *ux_code)
{
/*
* Try machine-dependent translation first.
*/
if (machine_exception(exception, code, subcode, ux_signal, ux_code))
return;
switch(exception) {
case EXC_BAD_ACCESS:
if (code == KERN_INVALID_ADDRESS)
*ux_signal = SIGSEGV;
else
*ux_signal = SIGBUS;
break;
case EXC_BAD_INSTRUCTION:
*ux_signal = SIGILL;
break;
...
Edit in relation to another of your questions
Please note that exception here does not refer to an exception at the level of the language, of the type one may catch with syntactical sugar like try{} catch{} blocks. Exception here refers to the actions of a CPU on encountering certain types of mistakes in your program (they may or may not be be fatal), like a null-pointer dereference, that require outside intervention.
When this happens, the CPU is said to raise what is commonly called either an exception or an interrupt. This means that the CPU saves what it was doing (the context) and deals with the exceptional situation.
To deal with such an exceptional situation, the CPU does not start executing any "exception-handling" code (catch-blocks or suchlike) in your application. It first gives the OS control, by starting to execute a kernel-provided piece of code called an interrupt service routine. This is a piece of code that figures out what happened to which process, and what to do about it. The OS thus has an opportunity to judge the situation, and take the action it wants.
The action it does for an invalid memory access (such as a null pointer dereference) is to signal the guilty process with EXC_BAD_ACCESS(SIGSEGV). The action it does for a misaligned memory access is to signal the guilty process with EXC_BAD_ACCESS(SIGBUS). There are many other exceptional situations and corresponding actions, not all of which involve signals.
We're now back in the context of your program. If your program receives the SIGSEGV or SIGBUS signals, it will invoke the signal handler that was installed for that signal, or the default one if none was. It is rare for people to install custom handlers for SIGSEGV and SIGBUS and the default handlers shut down your program, so what you usually get is your program being shut down.
This sort of exceptions is therefore completely unlike the sort one throws in try{}-blocks and catch{}es. Those exceptions are handled purely within the application, without involving the OS at all. Here what happens is that a throw statement is simply a glorified jump to the inner-most catch block that handles that exception. As the exception bubbles through the stack, it unwinds the stack behind it, running destructors and suchlike as needed.
Basically yes, indeed an EXC_BAD_ACCESS is usually paired with a SIGSEGV which is a signal that warns about the segmentation failure.
A segmentation failure is risen whenever you are working with a pointer that points to invalid data (maybe not belonging to the process, maybe read-only, maybe an invalid address in general).
Don't think about the segmentation fault in terms of "accessing an object", you are accessing a memory location, so an address. That address must be considered coherent by the OS memory protection system.
Not all errors which are related to accessing invalid data can be tracked by the memory manager, think about a pointer to a stack allocated variable, which is considered valid although its content is not valid anymore upon restoring the stack frame.

Assertion failed: xdrPtr && xdrPtr == *xdrLPP, file xx.cpp, line 2349

Have a system build using C++ Builder 2010 that after running for about 20 hours it starts firing of assertion failures.
Assertion failed: xdrPtr && xdrPtr == *xdrLPP, file xx.cpp, line 2349
Tried google on it like crazy but not much info. Some people seem to refer a bunch of different assertions in xx.cpp to shortcomings in the exception handling in C++ Builder. But I haven't found anything referencing this particular line in the file.
We have integrated madExcept and it seems like somewhere along the way this catches an out of memory exception, but not sure if it's connected. No matter what an assertion triggering doesn't seem correct.
Edit:
I found an instance of a if-statement that as part of it's statement used a function that could throw an exception. I wonder if this could be the culprit somehow messing up the flow of the exception handling or something?
Consider
if(foo() == 0) {
...
}
wrapped in a try catch block.
If an exception is thrown from within foo() so that no int is returned here how will the if statement react? I'm thinking it still might try to finish executing that line and this performing the if check on the return of the function which will barf since no int was returned. Is this well defined or is this undefined behaviour?
Wouldn't
int fooStatus = foo();
if(fooStatus == 0) {
...
}
be better (or should I say safer)?
Edit 2:
I just managed to get the assertion on my dev machine (the application just standing idle) without any exception about memory popping up and the app only consuming around 100 mb. So they were probably not connected.
Will try to see if I can catch it again and see around where it barfs.
Edit 3:
Managed to catch it. First comes an assertion failure notice like explained. Then the debugger shows me this exception notification.
If I break it takes me here in the code
It actually highlights the first code line after
pConnection->Open();
But it seems I can change this to anything and that line is still highlighted. So my guess is that the error is in the code above it somehow. I have seen more reports about people getting this type of assertion failure when working with databases in RAD Studio... hmmmm.
Update:
I found a thread that recursively called it's own Execute function if it wasn't able to reach the DB server. I think this is at least part of the issue. This will just keep on trying and as more and more worker threads spawn and also keep trying it can only end in disaster.
If madExcept is hinting that you have an out of memory condition, the assert could fail if the pointers are NULL (i.e. the allocation failed). What are the values of xdrPtr and xdrLPP when the assert occurs? Can you trace back to where they are allocated?
I would start looking for memory leaks.

Resources