Consider this code:
func doSomething() throws {
try callThrowingFunction1()
try callThrowingFunction2()
}
func userAction() {
do {
try doSomething()
} catch {
// display and log error
}
}
Say those inner functions can throw the same kind of errors and I would like to know if an error occurred in callThrowingFunction1() or in callThrowingFunction2().
As long as I'm in the debugger I can set a breakpoint for Swift errors on swift_willThrow, but if I would like to log the call stack on a user device, is there a way to do that?
Swift errors have no such thing as stack-trace yet (if will ever), and even Xcode can show stack-trace only if the error is un-handled by our code (and gets caught by Xcode directly instead).
Alternativly, your custom Error's constructor can store the stack-trace for later use, but in most cases errors are not custom, where you can't alter error's constructor (like errors of 3rd-party library).
But we can at least print stack-trace of where error(s) get catched, like:
do {
try ... // something that throws goes here
} catch let error as NSError {
print("Error: \(error)")
println(NSThread.callStackSymbols())
}
Exception breakpoint
If you just want to debug, without need to upload stack-trace to server, then Xcode's "Exception breakpoint" feature can help, like:
First place a normal-breakpoint near the failing logic.
Wait until Xcode pauses App on that line, enable Xcode's feature:
Finally, resume App, and wait untill exception is thrown.
Images are old, nowadays you see "Add Swift Error Breakpoint" or something like that as well (beside "Add Exception Breakpoint" option).
Related
I've run into the dreaded Reflection.emit issue in my webplayer build and am unable to locate what is triggering it. I'm currently commenting out code method by method and rebuilding to locate the cause and have narrowed it down to the below.
I'm not using JSON so the various JSON libraries aren't the cause, nor any of the other result suggestions returned by google.
How can i more easily go about locating the cause of this error. I have full stack trace on and well as full debugging, but all i get is the following console output.
NotSupportedException: C:\Program Files\Unity 2018.2.0b2\Editor\Data\il2cpp\libil2cpp\icalls\mscorlib\System.Reflection.Emit\AssemblyBuilder.cpp(20) : Unsupported internal call for IL2CPP:AssemblyBuilder::basic_init - System.Reflection.Emit is not supported.
Rethrow as TypeInitializationException: The type initializer for 'System.Reflection.Emit.DynamicMethod.AnonHostModuleHolder' threw an exception.
//NOTE: appM.procM is a C# .Net 4.x dynamic variable EG:
//public dynamic procM = GetProcClass(strProcName)
public void ShowProcList() {
/* Rest of method commented out*/
if(appM.procM == null){
procList.Initialize(appM.procM.lstNames, this);
}
/* Rest of method commented out*/
}
public void Initialize(List<string> lstNames, UIM um, string currProc=null) {
uiM = um;
//cleanup of the list before populating
foreach(Transform fld in Panel.transform) {
Destroy(fld.gameObject);
}
/* Rest of method commented out*/
}
Update: I narrowed down the problem line of code, but haven't closed the question as there's got to be an easier way than commenting out line by line and rebuilding.
For future searchers, the issue is the if(appM.procM == null) check. As procM is a dynamic variable reflection is used which kills AOT in webGL builds. No compiler warnings were generated to save myself from myself.
Nevermind, i am an idiot, The option Enable Exceptions under Player Settings was set to Full Without Stacktrace and not Full with Stacktrace.
The value Full With Stacktrace contains the pertinent data. Easily locatable in the browsers console. Warning that full debugging does increase build times and slow down the application.
Problem
I am working with PowerShell to create an application that uses a GUI created using Forms. While trying to maintain a modular programming style, I have more or less slammed into a wall that I cannot seem to find a way around, and was hoping the community could help.
In my application, I am trying to create custom error catching utilizing try/catch statements, but have found that when I call upon a factory function and that function has an error, the application will display said error as intended, but will continue to process as if it was successful...
I have even tried using exit and break, but end up with an "Unhandled Exception" error that immediately follows my custom error. I have even set $ErrorActionPreference = "Stop" but still get this problem.
Here is a simplified sample of my code so that you can see what is happening:
Button_Click = {
ValidatePathing -BackupPath $BackupPath.Text
If (!(Test-Path $BackupPath.Text)) {
# Attempt to Create it
}
# bunch of code
}
Function ValidatePathing ([string]$BackupPath){
Try {
If (!$BackupPath) {
throw "customError1"
}
If ($BackupPath -match "\|") {
throw "customError2"
}
}
Catch {
If ($_.Exception.Message -eq "customError1") {
[System.Windows.Forms.MessageBox]::Show("some message")
}
ElseIf ($_.Exception.Message -eq "customError2") {
[System.Windows.Forms.MessageBox]::Show("some message")
}
}
}
Unfortunately, when the code hits a section like ValidatePathing and a custom error happens, the error message will display as expected, but the code will then step over/through the section and continues to process the rest of the code, despite the error.
Question
Does anyone know PowerShell well enough to explain how to properly handle a situation like this so that the code stops running after hitting a nested error like this?
To be sure your Try is being handed a terminating error as it's designed to handle, utilize $PSCmdlet.ThrowTerminatingError(). This can take an ErrorRecord object as a constructor, allowing you to catch specific exception types.
UPDATE May 2021 - When I originally asked this question, the core thing that made this question relevant (for me) was that when rethrowing an exception from a catch via a simple throw (by itself), the original exception stack was lost. So that made using a catch to detect if an exception was thrown off-limits.
This incorrect loss-of-stack behavior was fixed sometime between when the question was asked (2017) and now. So a simple catch and rethrow (call throw with no other arguments) is now the most straightforward way to detect an exception was thrown from the finally block. Thanks to #JohnLBevan for his answer letting me know that rethrowing from the catch was no longer problematic.
ORIGINAL QUESTION:
I've got some code structured like this
try{
...
}
finally{
...
<code that may throw>
}
Of course one should generally avoid code that throws in a finally. But it can happen. And when it does, one unfortunate side effect is that the original exception is lost. So the first thing I'd like to do in the finally is log information about the exception thrown in the try, if one was thrown.
But how can I determine if an exception did occur in the try block, once I'm in the finally? Is there a slick way? I don't want to catch the exception in a catch. I can set a boolean at the end of the try which would indicate an exception was not thrown, but I'm not a big fan of having to do that every time. That would look like this:
$exceptionThrown = $true
try{
...
$exceptionThrown = $false
}
finally{
<if $exceptionThrown log info about it>
...
<code that may throw>
}
Can I do better?
If the only reason you're avoiding the catch block is because you don't want to affect the stack trace, you can use it then rethrow the error with the original line number by using throw with no arguments; thus rethrowing the original exactly as if you'd not used the catch block. For example:
$exceptionInfo = $null
try {
1/0 # cause some error
} catch {
$exceptionInfo = $_.Exception # you could set a flag / whatever here; without knowing your requirement I can't advise further
throw # you said you didn't want to catch it... but if you just don't want to impact the stack trace this is fine as we're rethrowing the original exception; not throwing a new one
} finally {
if ($null -eq $exceptionInfo) {
Write-Information 'Completed Successfully' -InformationAction Continue
} else {
Write-Warning "An error occurred $exceptionInfo"
}
}
If you don't want to use a catch block and don't want to use some variable you've defined to flag whether an exception's occurred, you could use $Error; though you may need to clear it first as it will contain all errors which have been raised in the current session...
$Error.Clear()
try {
1/0
} finally {
if ($Error.Count) {
Write-Warning "An error occurred $($Error[0])"
} else {
Write-Information 'Completed Successfully' -InformationAction Continue
}
}
Generally you shouldn't need to determine whether something was successful in a finally block though; rather:
If you have logic that you only want to occur if the command is successful, place it in the TRY block after the line that may cause an exception.
If you have logic that you only want to occur if the command hits an error, place it in the catch block (and use throw if you want to rethrow the original exception so that it still bubbles up afterwards).
If you have logic that should run in either case, that's where the finally block comes in. Sometimes you may need to know the state of some component here (e.g. is a connection to your database still open) and that state may have changed due to the exception... If that's the case, normally such components should provide their own flags.
Below's a rough illustration; the actual example's a bit poor as I couldn't think of a good & succinct real world example scenario; but hopefully you get the idea.
try {
$con = Get-MyDbConnection
New-DbRecord -Connection $con -Data $data
} catch {
Write-Log $_.Exception
} finally {
if (($null -ne $con) -and ($con.IsConnected)) {
$con.Disconnect()
}
}
This page about Powershell 5.1 doesn't explicitly cover the case of throwing an exception inside a "finally" block, but says that Powershell behavior is similar to C# behavior. And the accepted answer to this SO question about C# behavior indicates that:
the code in the "finally" block beyond the point where the exception was thrown is not executed, and
if the "finally" block was executed during the handling of an earlier exception, then that first exception is lost
So I think what you really want is something like this:
try { ... set flag ... }
catch { ... adjust flag ... }
finally { ... check flag ... }
The catch block only executes if there was an exception thrown in the "try" block, but the "finally" block happens in every case (and can tell whether or not an exception was thrown in the original "try" block by checking the value of the flag).
Of course if an exception can be thrown in the "finally" block and you want to handle that, then you're going to need to wrap that whole business in another "try".
I am exploring the usage of SWTWorkbenchBot to use in my automation of an eclipse-based project. However, something seems weird when trying to get the "Console" view.
SWTWorkbenchBot workbenchBot = new SWTWorkbenchBot();
String consoleTitle = "Console";
try {
workbenchBot.viewByTitle(consoleTitle).show();
System.out.println("Got the Console view");
} catch (Exception e) {
for (SWTBotView view : workbenchBot.views()) {
System.out.println(view.getTitle() + "\t" + v.getTitle().equals(consoleTitle));
}
}
From the above code, I assume one of the following 2 cases holds:
Either the code will exit with "Got the Console view" message printed
Or the message "Got the Console view" message NOT printed because the "Console" view was not found and an exception of type WidgetNotFoundException is thrown and the code inside the catch will be executed. The output should NOT contain the title "Console" or at least, next to all view titles, false should be printed.
Surprisingly, this is not happening. The message "Got the Console view" is NOT printed, yet if you look at the list of the view, you see that there exists a line Console true which means that the SWTWorkbenchBot could not get the console view using the method .viewByTitle() but he knows that exists by checking the .views() content.
The above code works fine for any view except for the Console view. Am I doing something wrong here? Thanks in advance.
If I look into my running Eclipse the View is called "Console (General)". You really should not rely on any names if you have the possibility to reference the view with an Id, check if the follwing snippet will work
workbenchBot.viewById("org.eclipse.ui.console.ConsoleView").show();
Just a sidenote: You should make ui Test code a bit more robust, UI tests tend to fail caused by timings, ui-states, overlapping windows, so fail early with a clear statement why the test failed.
[...]
SWTBotView view = workbenchBot.viewByTitle(consoleTitle);
assertNotNull("Console was not found", view);
try {
view.show()
} catch (Exception e) {
fail("Error occured while opening console")
}
[...]
new SWTWorkbenchBot().viewByPartName("Console").show();
should do the job.
What you see in the UI is the value returned by org.eclipse.ui.IWorkbenchPartReference.getPartName() but not the value returned by org.eclipse.ui.IWorkbenchPartReference.getTitle().
With Swift now some functions are marked with throws, and this force the developers to call the function inside a do - try catch block.
But how the developer can know the list of different exceptions thrown by that function?
As reference, here is a line of Java code:
static void employeeAge(int age) throws MyExceptionA,MyExceptionB
Here is clear that the exceptions are 2 MyExceptionA and MyExceptionB and the developer can decide to act differently depends of the error.
Can we achieve the same on Swift?
When the Swift docs says a function throws, they mean that it throws an ErrorType (in Cocoa APIs usually an NSError), not an exception.
Consider the following do-try-catch flow for NSFileManager's createDirectoryAtPath:
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
do {
try NSFileManager.defaultManager().createDirectoryAtPath(documentsPath, withIntermediateDirectories: false, attributes: nil)
} catch {
// 'error' variable automatically populated
print(error)
print(error.dynamicType)
}
createDirectoryAtPath will fail because the documents directory already exists. Logging the dynamicType of the error shows that it is in fact an NSError object:
Error Domain=NSCocoaErrorDomain Code=516 "The file “Documents” couldn’t be saved in the folder “35B0B3BF-D502-4BA0-A991-D07568AB87C6” because a file with the same name already exists." UserInfo={NSFilePath=/Users/jal/Library/Developer/CoreSimulator/Devices/E8A35774-C9B7-42F0-93F1-8103FBBC7118/data/Containers/Data/Application/35B0B3BF-D502-4BA0-A991-D07568AB87C6/Documents, NSUnderlyingError=0x7fa88bd14410 {Error Domain=NSPOSIXErrorDomain Code=17 "File exists"}}
NSError
In order to see the different types of errors a function can throw, you would have to examine the error for information to determine the type of error thrown, and how to handle each error. In the case of NSError this would be its domain, code, and description.
In this particular case, a directory already exists at that path, so the file manager cannot create a new directory. An example of another reason why this operation could fail would be if the file manager did not have write access. That would be error code 256.
I had the exact same question as the OP. Since no one really answered the question as he asked (and I as well), here goes my contribution.
In Swift 3 and Xcode 8.3.3 you would do as follows to treat the individual exceptions. Below I will give you an example with FileManager.
First you will have only one catch block to catch whatever error the method throws at you. Then you will cast that error as an NSError. Contrary to the Error protocol in Swift, NSError is a REAL error class. Then you can extract that error's code in a switch statement. You will have to know what domain that method throws error from and then find the error codes in the appropriate header file.
In my example below, the file related errors are thrown in the NSCocoaErrorDomain and these errors codes are defined/listed in Foundation/FoundationErrors.h. In my computer, they are located at
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/FoundationErrors.h
for macOS apps and at
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/Foundation.framework/Headers/
for iPhone apps.
So here is an example:
let home = FileManager.default.homeDirectoryForCurrentUser
let file = home.appendingPathComponent("file")
do {
let loadedString = try String(contentsOf: file)
}
catch {
let realError = error as NSError // As weird as it looks, Xcode actually wants this forced conversion
print(realError.localizedDescription)
switch realError.code {
case 257: // No permission
handleNoPermission()
case 260: // File not found
handleFileNotFound()
default:
handleUndefinedError()
}
}
The .localizedDescription contains a user friendly message in your user's language about that error. If file is not found above it prints: The file “file” couldn’t be opened because there is no such file. in English. It is meant to be used directly in the error dialogs you present to your user.
You may also find more information about what error is thrown by each domain here: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorObjectsDomains/ErrorObjectsDomains.html
You write a pattern after catch to indicate what errors that clause can handle.
do {
try expression
statements
} catch pattern 1 {
statements
} catch pattern 2 where condition {
statements
}
See section Handling Errors Using Do-Catch of Swift Programming Language