Debugging with semaphores in Xcode - Grand Central Dispatch - iOS - ios

Say have a few blocks of code in my project with this pattern:
dispatch_semaphore_wait(mySemaphore);
// Arbitrary code here that I could get stuck on and not signal
dispatch_semaphore_signal(mySemaphore);
And let's say I pause in my debugger to find that I'm stuck on:
dispatch_semaphore_wait(mySemaphore);
How can I easily see where the semaphore was last consumed? As in, where can I see dispatch_semaphore_wait(mySemaphore); was called and got through to the next line of code? The trivial way would be to use NSLog's, but is there a fancier/faster way to do this in the debugger with Xcode 4?

You can print debugDescription of the semaphore object in the debugger (e.g. via po), which will give you the current and original value (i.e. value at creation) of the semaphore.
As long as current value < 0, dispatch_semaphore_wait will wait for somebody else to dispatch_semaphore_signal to increment the value.
There is currently no automatic built-in way to trace calls to dispatch_semaphore_signal/dispatch_semaphore_wait over time, but that is a useful feature request to file at bugreport.apple.com
One way to trace this yourself would be by creating symbolic breakpoints on those functions in Xcode, adding a 'Debugger Command' breakpoint action that executes bt and setting the flag to "Automatically continue after evaluating" the breakpoint.
Another option would be to use DTrace pid probes to trace those functions with an action that calls ustack().

Related

How to break out of an assert in iOS / swift

I've hit an assertion in code and wondering if there's a way to create a wrapper around the assert that would enable breaking out and continuing execution or some other function that would enable a way to suppress the assert through the lldb debugger.
assert(condition(), makeCriticalEvent().event.description, file: fileID, line: UInt(line))
This is the standard assertion in apples libraries here. When I hit this assertion I tried continuing execution but it stays stuck at the assertion. I'd like to silence the assertion (likely through the lldb debugger by typing some command). Anyone have an idea how to do this?
You have to do two things. First, you have to tell lldb to suppress the SIGABRT signal that the assert delivers. Do this by running:
(lldb) process handle SIGABRT -p 0
in lldb. Normally SIGABRT is not maskable, so I was a little surprised this worked. Maybe because this is a SIGABRT the process sends itself? I don't think there's any guarantee suppressing SIGABRT's has to work in the debugger so YMMV, but it seems to currently. Anyway, do this when you've hit the assert.
Then you need to forcibly unwind the assert part of the stack. You can do that using thread return, which returns to the thread above the currently selected one w/o executing the code in that frame or any of the others below it. So just select the frame that caused the assert, go down one frame on the stacks and do thread return.
Now when you continue you won't hit the abort and you'll be back in your code.

print - Background or main thread operation

This might sound quite basic and stupid but it has been bothering me for a while. How can print be classified in terms of operation - main or background ?
As a small test, on putting print in a background task - web service call :
Webservice().loadHeadlinesForSource(source: source) { headlines in
print("background print")
self.headlineViewModels = headlines.map(HeadlineViewModel.init)
DispatchQueue.main.async {
print("main thread print")
completion()
}
}
Both the print statements get printed. From previous experience, if print was a main thread task, Xcode would have given me a warning saying that I need to put that in main thread. This is an evidence that print is not a main thread operation. Note that I am not saying print is a background task.
However, I have this understanding that since print displays output on Console, it is not a background operation. As a matter of fact all logging operations are not.
How would one justify the classification ?
It seems what you consider to be a main thread operation is a call that needs to be performed on the main thread. From that perspective you are correct and have found an evidence of this call not being a main thread operation.
But does this have anything to do with anything else? Internally if needed this method may still execute its real operation on the main thread or any other thread for what we care. So in this sense a main thread operation is a restriction that call needs to be performed on main thread but has nothing to do with its execution or multithreading.
Without looking into what print does in terms of coding we can see that it works across multiple "computers". You can run your app on your device (iPhone) while plugged and Xcode on your computer will print out logs. This makes a suspicion that print is much like call to the remote server in which case the server is responsible for serializing the events so it makes no difference what thread the client is on. There are other possibilities such as dropping logs into file and then sending it which really makes little difference.
So How can print be classified in terms of operation - main or background? The answer is probably none. The call is not restricted to any thread so it is not main. It will probably lock whatever thread it is on until the operation is complete so it is not background either. Think of it like Data(contentsOf: <#T##URL#>) which will block the thread until data from given URL is retrieved (or exception is thrown).

XCode not stopping on breakpoint in method called from LLDB

XCode 7.2.1
iPad Retina iOS 9.2 Simulator
I have several breakpoints set in a particular class in an XCode project.
Everything I discuss below takes place in this one class file.
I set the breakpoints on -(int16_t)areaNbr by clicking in the gutter, and set no conditions or anything on them. I confirmed they existed as far as LLDB is concerned by running breakpoint list from the LLDB prompt.
The project scheme is set to build for debugging, not release.
I run the project in the simulator, and stop at a breakpoint in a different method than the one in question, at which time I want to go to the LLDB prompt and call po [self areaNbr] and step through areaNbr.
Please note, as this may be quite relevant, I have NO code in the project itself that calls
-(int16_t)areaNbr
Now, I CAN get this to stop at my breakpoints on -(int16_t)areaNbr if I add some code to the project that calls the method.
For example, if I add something like NSLog(#"... %d", [self areaNbr])
I know the issue has nothing to do with compiling away the method simply because nothing calls it, because if that were true, then my call to po [self areaNbr] wouldn't be spitting out the result to the debugger window as pictured below. So the method is being compiled, and certainly recognized as existing by the debugger for execution purposes... just not for stepping purposes.
FYI, [self area] is returning "Area01"
Calling breakpoint list in LLDB returns the following
By default, lldb does not stop at breakpoints in hand-called code. The majority of folks use expr & expr -O -- i.e. po to print values & objects and were annoyed if they stopped at breakpoints they had set for other purposes.
However, it is easy to control this behavior, just use:
(lldb) expr -i 0 -- [self areaNbr]
Then you will stop at your breakpoint.
In this example, I left out the -O which is the object printing part, since if you just want to call this method, you likely don't care about calling description on the result after the expression is evaluated.
You can see all the options for expression evaluation by doing:
(lldb) help expr

Breakpoint Debug proper usage iOS?

I put breakpoint. I used command ⌥⌘-click on breakpoint.
It showed me following options.
How can I use these options.
1. AppleScript
2. Capture GPU Frame
3. Debugger Command
4. Log Message
5. Shell Command
6. Sound
There are other options
1. Condition
2. Ignore
3. Action
4. Options
What are these options. How are they working?
You can read this detailed tutorial on breakpoints options: https://www.bignerdranch.com/blog/xcode-breakpoint-wizardry/
Short summary:
Condition: if condition evaluated to true, breakpoint is triggered.
Ignore is self explaining. Like "ignore first 2 passes".
Action: what to do if breakpoint is triggered.
Options: set if you do not want to stop on this breakpoint in XCode
For action field you can choose what to do when breakpoint is triggered. Possible values is:
AppleScript: execute entered AppleScript code
Capture GPU frame: capture OpenGL frame contents
Debugger Command: execute entered GDB command
Log Message: log entered message to console
Shell Command: execute entered shell command
Sound: play a sound file
These options may be used to perform additional actions once the debugger hits this breakpoint.
The "Log Message", for example, can be very useful as it lets you print automatically collected data like the hit count for this breakpoint, the name of the method it's in, values of variables and other expressions.
Using the same principal, you can have the debugger run an Apple script, execute shell commands, etc.
You can also check the "Automatically continue after evaluating actions" so the debugger won't actually break while hitting it - but the action will still be executed.
There are even more advanced options you can utilize like performing the action only when a certain condition is met, ignore the breakpoint unless it has a certain minimum of hits, and even chaining several operations (+ and - buttons).

Resart a task in FreeRTOS

I have a specific task routine which performs some operations in a specific order, and these operations handle few volatile variables. There is a specific interrupt which updates these volatile variables asynchronously. Hence, the task routine should restart if such an interrupt occurs. Normally FreeRTOS will resume the task, but this will result in wrong derived values, hence the requirement for restarting the routine. I also cannot keep the task routine under critical section, because I should not be missing any interrupts.
Is there a way in FreeRTOS with which I can achieve this? Like a vtaskRestart API. I could have deleted the task and re-created it, but this adds a lot of memory management complications, which I would like to avoid. Currently my only option is to add checks in the routine on a flag to see if a context switch have occured and if yes, restart, else continue.
Googling did not fetch any clue on this. Seems like people never faced such a problem or may be its that this design is poor. In FreeRTOS forum, few who asked for a task-restart didn't seem to have this same problem. stackOverflow didn't have a result on freertos + task + restart. So, this could be the first post with this tag combination ;)
Can someone please tell me if this is directly possible in FreeRTOS?
You can use semaphore for this purpose. If you decide using semaphore, you should do the steps below.
Firstly, you should create a binary semaphore.
The semaphore must be given in the interrupt routine with
xSemaphoreGiveFromISR( Example_xSemaphore, &xHigherPriorityTaskWoken
);
And, you must check taking semaphore in the task.
void vExample_Task( void * pvParameters )
{
for( ;; )
{
if (xSemaphoreTake( Example_xSemaphore, Example_PROCESS_TIME)==pdTRUE)
{
}
}
}
For this purpose you should use a queue and use the queue peek function to yield at your volatile data.
I'm using it as I have a real time timer and this way I make the time available to all my task, without any blocking.
Here it how it goes:
Declare the queue:
xQueueHandle RTC_Time_Queue;
Create the queue of 1 element:
RTC_Time_Queue = xQueueCreate( 1, sizeof(your volatile struct) );
Overwrite the queue everytime your interrupt occurs:
xQueueOverwriteFromISR(RTC_Time_Queue, (void*) &time);
And from other task peek the queue:
xQueuePeek(RTC_GetReadQueue(), (void*) &TheTime, 0);
The 0 at the end of xQueuePeek means you don't want to wait if the queue is empty. The queue peek won't delete the value in the queue so it will be present every time you peek and the code will never stop.
Also you should avoid having variable being accessed from ISR and the RTOS code as you may get unexpected corruption.

Resources