I am on macOSX (Sierra), not iOS, Objective-C, Xcode9.
I have an application with implemented applescript classes, XCode compiles them for me. Whenever i call an applescript method from within an *.m file (and from a background thread!) i dispatch_sync it to the main thread (as applescript needs to be executed in the main thread) - sync cause i need the result to continue.
I'd like to show you with a simple example:
Applescript:
on openFile_filePath(filePath)
try
tell application "Adobe InDesign CC 2018"
set myDoc to open (filePath as string)
return id of myDoc
end tell
end
return 0
end
Objective-C
// Method is running in a background thread
// appleScriptHelper is properly instantinated
__block NSInteger docID = 0;
NSString* someFile = #"/Users/user/Desktop/";
dispatch_sync(dispatch_get_main_queue(), ^{
docID = [self.appleScriptHelper openFile:someFile];
});
This runs smooth - as long as InDesign responds! Sometimes, InDesign freezes and then my whole app freezes cause it basically waits forever on the main thread.
What i tried:
I cannot use a timer cause the main thread is blocked anyways and i cant pass a "cancel" message - cause Applescript is busy anyways waiting for something never happen.
In addition it is not possible to work with "with timeout of x seconds" in applescript when compiled from XCode (just doesnt work as mentioned in other posts).
I tried it with NSOperations but as i need to dispatch to the mainThread... still the same issue.
So my question is: Is there any way i can STOP the whole dispatch_sync block after a time of x seconds? Or is there any other possibility to keep the app running and not being locked up forever through InDesign freeze?
Note: The implementation works fine - please don't recommend 'use NSApplescript' or 'use Scripting Bridge'.
Reasons: ScriptingBridge - it's almost impossible to create a working HEADER file for InDesign (it almost weights 15 MB and throws tons of compiler errors - i did fix that once with lot of manual work just to see it not working anymore for the next Version of InDesign). NSApplescript is fine as long as you have simple scripts which is not the case.
Any help appreciated
Were NSAppleScript sufficient for your needs, I'd say use NSUserAppleScriptTask which runs scripts out of process with async completion callbacks. And yes, as you say, Scripting Bridge is utterly unfit for non-trivial automation, especially any involving large complex crusty Carbon apps like Adobe's, so don't waste a second on that.
There is AppleEventBridge/SwiftAE, but with Apple shuffling off the whole AS/AE infrastructure to quietly die off, I don't promote or support those any more, so maxima caveat emptor. (I still use Python appscript for my own Adobe app automation,btw, and it continues to blow everything else out the water, but I won't be surprised if the whole industry eventually goes Windows as the only professional-oriented platform left.)
..
The problem with using AppleScript-ObjC* is that AppleScript component (aka interpreter) instances are not thread-safe: you can instantiate them on any thread you like, but you can only use them on that thread, not from others. ASOC doesn't let you control any of this stuff for yourself; neither does NSAppleScript. (OSAKit does, but it's as painful to use as NSAppleScript is.) So ASOC code is de facto limited to running on the main thread only.
If you're stuck with using ASOC, I think your best bet is to push that code out into a subprocess that your main process talks to asynchronously via XPC Services or whatever. That'll avoid blocking your main process's main event loop (which then blocks its GUI) while allowing ASOC to do its own thing independently.
p.s. Another problem with ASOC is that changes in 10.13's bridgesupport files have changed/broken how C APIs are mapped to AS, which can break existing ASOC-based scripts. (I've stopped recommending ASOC unless/until that's fixed.)
Related
How do you debug an RTOS application? I am using KEIL µVision and when I hit debug, the program steps through the main function until the function that initializes the RTOS kernel and then you can't step any further. The code itself works though. It is not mine btw, but I have to work on it. Is this normal behavior with RTOS applications or is this related to the program?
Yes, this is normal. You need to set breakpoints in the source code for the tasks that were created in main(): the only purpose of main() in a FreeRTOS application is to :
initialize the hardware,
create the resources (timers, semaphores...) and tasks your application will need,
start the scheduler
The application should never return from vTaskStartScheduler() if they were enough resources available.
Put break-points at the entry point of each task you need to debug. When you step the over the scheduler start (or simply run) the debugger will halts at the first task that runs. When that task blocks, some other task will be selected to run according to the scheduling rules.
Generally when debugging and you reach a blocking call, step-over it, other tasks may run and the debugger will stop at the next line only when the task becomes ready (depending on the nature of the blocking call). Often you will want to predict what task will run as a result of the call, and put a breakpoint in that task. For example if you issue a message send, you might place a breakpoint after the message receive call of the receiving task.
The point is you cannot "step-through" a context switch unless you have the RTOS source or do it at the assembler level, which is seldom useful or productive, and will not work for preemption.
You get a somewhat better RTOS debug experience and tool support in Keil if you use Keil's own RTX5 RTOS rather then FreeRTOS, but all of the above remains true.
Yes, this is an expected behaviour. The best way to debug a RTOS application is to place breakpoints at all tasks, key function entry points and step debug.
The debugger supports various methods of single-stepping through an application as in below link.
http://www.keil.com/products/uvision/db_exe_step.asp
Typical challenges in debugging RTOS application can be dealing with interrupt handling, synchronization issues and register/memory corruption.
Keil µVision's System Analyzer enables one to view the program execution time frame, status of each thread. It shall also help in viewing interrupts, exceptions if tracer is enabled.
in my project i injected a DLL(64-bit Windows 10) in to a external process with Manual-map & Thread-hijacking and i do some stuff in there.
In current state i use "RtlCreateUserThread" to create a new thread and do some extra workload in there to distribute it for better performance.
My question is now... Is it possible to access other threads from the current process (hijack it) and add your own workload/code there. Without creating a new thread?
I didn't found anything helpful yet in the internet and the code i used and modified for Thread-hijacking seems to only work for a DLL file. Because i am pretty new to C++ i am still learning i am already thankful for any help.
(If you want to see the source for injector Google GHInjector your find the library on github.)
It is possible, but so complicated and may not work in all cases.
You need to splice existing thread's machine codes, so you will need write access to code page memory.
Logic:
find thread id and thread handle, then suspend thread with SuspendThread WINAPI call
suspended thread can be in wait state or in system DLL call now, so you need to analyze current execution stack, backtrace it and find execution address from application space. You need API functions StackWalk, and PDB files in some cases. Also it depends on running architecture (x86, amd64, ...). Walk through stack until your EIP/RIP will not be in application memory address space
decode machine instruction (it will be 'call') and splice next instructions to your function call. You need to use __declspec(naked) declared function or ASM implemented one for execute your code and replaced instructions.
ResumeThread
This method may work only once because no guarantees that application code is executed in loop.
I'm using a Pharo 6.1 image to do some CSV file processing. Sometimes my image just becomes unresponsive — I have to terminate the Pharo VM from Task Manager.
Is it necessary to use somethings like:
ensure:[toStream close]
ensure:[fromStream close]
What's a simple but reliable approach to reading and especially writing files with Pharo?
The image is not really unresponsive but the UI thread for sure is when you do a long operation like reading a big CSV file.
The best would be to for a process for doing it.
Like in:
[ target doSomeLongThing ] fork.
You can view the process in the process browser from the world menu and terminate it there.
Now that is not really something one will think about when trying things out interactively in a playground.
What I do to alleviate this situation is twofold:
Put these things in a test. Why? Because tests have a maximum duration and if things are stuck, they will come back with a time exceeded notification from the test.
Start the Zinc REPL on a port, so that I can access the system from a web browser if the UI thread is kind of stuck and restart the UI thread.
I wish the interrupt key would work in all cases but well, it doesn't and is a solid annoyance.
I am of the opinion that images should be considered as discardable artifacts and CI job should be building them regularly (like daily) so that we have some recovery path.
This is not really cool as yes, using an image and being able to come back to it without having to rebuild stuff all the time when doing explorations shouldn't frustrate us with UI thread blockages. I hate that. I have an image that is stuck on restart from some Glamour problem, it is infuriating as it cannot be debugged or anything.
You can also use:
(FileLocation imageDirectory / 'somefile.csv') asFileReference readStreamDo: [ :stream |
"do something with the stream" ].
This will do the ensure: bit for you. Cleaner. Easier.
For CSV, also give a shot to NeoCSV as it will do the file handling for you as well.
HTH
I want to accomplish following effect:
User presses the button;
VoiceOver speaks aloud a "processing" sentence;
Performing some heavy processing.
Everything is being ran in main thread and I don't want GUI to be able to update in that time. For that, I'd like the method not to return before the end of heavy processing. I have following code:
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,
#"Processing");
heavyProcessing();
The problem is, that VoiceOver speaks the information after heavy processing has been completed.
How to make VoiceOver speak out the information "asynchronously", before method finishes and returns control to the main loop? If necessary, the heavy processing may be ran in another thread.
That would be because, if the main thread is doing heavy processing, it can't do anything else and that would include initiating voice over requests.
In fact, there are many things that happen on the main thread that mean that you never want to do lengthy processing on it. Your app can't, for instance, respond to notifications from the OS like low memory warnings. If that's the case, iOS might kill your app thinking it has hung.
What you need to do is run your heavy processing on a background thread - I recommend using NSOperationQueue - and disable the controls you don't want to work while it is happening.
I want to copy a file to a FTP server using wxFTP, but I would like to do this without blocking the UI, and much better, while displaying a progress bar. Can I do this without extra thread?
I'm using wxLua, but I can adapt a solution written in any language as long as it uses a wxWidgets binding.
Try using wx.lib.delayedresult. It's available in wxPython, but maybe also it is in your wxWidgets library too. It creates separate worker thread and is called with a consumer function that is called once worker thread finishes his job. Quite useful thing.
See wxPython docs for details.
What's wrong with starting your own Thread for this?
You could check the streams canRead() method periodically (through a timer or in the event loop, maybe) and only read when it returns true, but it'll probably be a lot more complex than just starting a separate thread.