Crash-proofing Mac Cocoa application - cocoa

In my Cocoa application I need to run a task that uses unstable unfixable code. It takes little input, works independently from the rest of the app, and generates thousands of ObjC objects as a result.
How can I run the unstable part and let it crash without taking down whole application?
Is it possible to fork() Cocoa application? How UI, threads, GC, KVO, runloops are going to behave when forked?
Can I avoid creating standalone executable launched via NSTask?
If I launch separate process, how can I send and receive ObjC object instances? (I'd rather not serialize/unserialize them myself, and I need to keep them after child process ends).
How does OS X handle this problem for Spotlight and Quicklook plugins?

Is it possible to fork() Cocoa application?
Yes, but you pretty much have to exec immediately. Core Foundation will throw an exception if you try to use certain Cocoa methods or CF functions between fork and exec (or without execking at all). You might get away with some things (I was able to ask a window its frame, for example), but nothing is safe.
Launching an NSTask, of course, counts as fork and exec together, averting the problems of skipping or postponing the exec.
How UI, threads, GC, KVO, runloops are going to behave when forked?
UI: Windows (the actual ones on the screen) are not duplicated. Of course, you can't talk to your NSWindow and NSView objects anyway.
Threads: Not carried over to the subprocess. This is not as good as it may sound, as problem cases abound; for one, another thread might have held a lock in the parent, which remains locked in the child even though the thread that held it is absent.
GC: Well, the garbage collector runs on a thread…
KVO: Should be fine, since observation is normally triggered either explicitly or by KVO-supplied wrapper accessors.
Run loops: One per thread, so the main thread's run loop should still exist, but it will die if you return to it.
Can I avoid creating standalone executable launched via NSTask?
Nope.
If I launch separate process, how can I send and receive ObjC object instances?
If you don't exec, you don't.
Otherwise, you can use DO.
(I'd rather not serialize/unserialize them myself, and I need to keep them after child process ends).
Then you'll need to make a copy in the parent process. I don't know whether you can use copyWithZone: here; probably not. I suspect you will have to do some sort of plist- or archive-based serialization/unserialization.
How does OS X handle this problem for Spotlight and Quicklook plugins?
Spotlight has mdworker; Quick Look has something similar.

I use Distributed Objects to communicate between my cocoa program and a separate (unreliable) worker program. I start the worker as a NSTask. Distributed objects are very elegantly put together.

Related

NSOperation for persistent thread

I have an external tool (written in perl) that does work through a C++ object interface. The launching and tear-down take time so I'd like to have an NSOperationQueue and 4 NSOperation threads that run throughout the life of my app but only do work when I feed them a file to work on. I can round-robin feed them as every file will take roughly the same amount of work.
How can I best do this, or is this asking too much of NSOperation in a way it was not designed to do.
I have tried a normal NSOperation task for each file and the launch & tear-down of the perl tool slows things down and sometimes hangs (not sure why - but seems related to the launch process happening too quickly in sequence).
I'm looking to launch the perl tool once on each of 4 threads and then keep them around for the life of the app as the perl tool will stay open waiting for commands... but those commands have to come from the thread that were launched from.

Questions about SetWindowsHookEx() and hooking

Here is a little background information. I'm working on replacing a dll that has been used in a dll injection technique via the AppInit_DLLs registry entry. Its purpose was to be present in every process and set hooks into the GDI32.dll to gather information about printing. This is kind of a funky way to get what we want. The .dll itself is over 10 years old (written in Visual Studio 97) and we'd like to replace it with something a little less invasive than an injected dll.
It appears SetWindowsHookEx() maybe what we are looking for. I've been having some trouble with it, but I've also had some discussions with co-workers about whether or not this tree is worth barking up. Here are some questions that we could not determine:
When we hook a routine out of a dll, for example StartDoc() from GDI32.dll, do we really get a notification every time any other process uses that rotuine out of that dll? This is kind of the functionality we were getting with our injected .dll and we need the same functionality going forward.
When the hook is triggered, does the hook handling procedure run in the process space of the process that initiated the actual call, or in the process space of the process that set up the hook? My opinion is that it has to run in the process space of the process that called the routine. For example, if a program calls StartDoc() from GDI32.dll, it will have the hook handling procedure code "injected" into its space and executed. Otherwise, there would have to be some inter-process communication that automatically gets set up between the calling process and the process that set up the hook, and I just don't see that as being the case. Also, its kind of necessary that this hook handling routine run in the process space of the calling process since one of the things it needs to know is the name of that calling process, and I'm not sure on how to get that information if it wasn't actually running in that process.
If the hook handling routine is written using the .NET managed environment, will it break when getting hooked into a process not utilizing the .NET managed environment? We'd really like to move away from C++ here and use C#, but what would happen if we our hook gets called from a process that isn't managed? As stated before, I think that our hook handling procedure will run in the process that originally called the routine that was hooked. But if this is true, than I would think that we'd run into trouble if this process was not using the .NET run time environment, but the incoming hooked handling code is.
Yes.
Generally, it's the former: it executes in the context of the process whose event it is hooking.
After a successful call to SetWindowsHookEx, the operating system automatically injects the hook DLL (the one that contains the callback function) into the address space of all target processes that meet the requirements for the specified hook type. (Of course, the hooking code is not necessarily injected immediately.)
The exception to this general rule are the low-level keyboard and mouse hooks (WH_LL_KEYBOARD and WH_LL_MOUSE). Since those hook types are not injected into the client processes, the callback is called in the same thread that originally called SetWindowsHookEx.
That last point is important to keep in mind to answer your third question. Because the low-level keyboard and mouse hooks are the only two global hooks that do not require DLL injection, they are also the only two types of hooks that can be written in managed .NET code.
For the other hook types, your concerns expressed in the question are precisely correct. You would need to write these hook DLLs in C or C++. Of course, the rest of your application's pieces could still be written in a managed language. The only thing that matters is the hook DLL.
You might consider looking into either Microsoft Detours or EasyHook.

How to avoid the White Blank Screen?

Using VB6
At the time of executing, it showing white blank screen while it was working with database,
How to avoid the white blank screen in VB6.
WHITE BLANK SCREEN MEANS HANGING (WHEN IT WAS WORKING WITH DATABASE).
How to avoid that?
I assume you mean that the GUI won't redraw itself when executing a long-running operation. (Shouldn't actually be that visible starting with Vista, but I digress).
If your long-running operation is composed of several steps or tight loops, then you can sprinkle a call to DoEvents every once in a while to cause the form to remain somewhat responsive even when doing work.
Another option would be to migrate your long-running work into a separate thread but last I looked this wasn't exactly trivial or easily possible in VB6.
You should work with data base in separate thread, and any time-consuming operation should be run in a separate thread too. In this case your user interface won't be frozen.
I posted this as an answer to another question, but the pattern applies here as well:
VB6, on its own, is single threaded. However, you can make it somewhat multithreaded via the use of ActiveX EXE that run in their own process, yet still are tethered to the original VB6-created EXE.
What I've used in the past is the Timer object in conjunction with an ActiveX EXE. This approach will give you an ability to localize all the downloading logic in one place, control it like you control a regular object and have it run in a separate EXE, thus by default making it multi-threaded.
So the way this works is like so:
You call the LongRunningOperation method on the ActiveX EXE object
In the LongRunningOperation method, you instantiate the Timer and have it kick off almost immediately.
You get out of the LongRunningOperation method, thus giving control back to the entity that called it.
Then you communicate back to the main app via Events (e.g. LongRunningOperationProgress or LongRunningOperationComplete, etc...)
I recommend the Timer object from Karl Petersen.
This is actually the same problem as your "How to exit the program immediately" question. In both cases, the problem is that your database operation is blocking the VB6 program from executing.
The answer you accepted for the other question - use ADO to carry out the operations asynchronously - will also solve this blank screen problem.
Or if you prefer, follow one of my suggestions in my answer to your other question and use a .NET background worker component through Interop like this.
Or follow my other suggestion and delegate the database work to an ActiveX exe like this. EDIT AngryHacker's nice answer to this question uses this method.
Your first instinct should be to put your resource-intensive operations in a separate thread. This is a bit difficult in VB6, although possible (but not recommended) if you invoke the native CreateThread API.
You can also migrate to VB.NET, and use Thread objects natively.

How to create Chrome like application in Delphi which runs multiple processes inside one Window?

Is it possible to create an "application group" which would run under one window, but in separate processes, like in Chrome browser? I'd like to divide one application into multiple parts, so that one crashing or jamming process cannot take down others, but still keep the look and feel as close to original system as possible.
I know the Chrome source is available, but is there anything even half ready made for Delphi?
I guess basically you would create multiple processes each of which creates a window/form. One of the processes has the master window in which every child window is embedded. That is as simple as calling SetParent. The windows in different processes would talk to each other using an IPC (Inter Process Communication) mechanism like named pipes or window messages.
See this question for an embedding example of using SetParent in Delphi. See this question for an example of using named pipes in Delphi.
Have a look at the Delphi code of HeidiSQL. It's a great open source MySQL client that implements this mechanism.
Read this newsitem that was posted when Chrome was released:
"Google playing catch-up with HeidiSQL?"
:-)
(source: heidisql.com)
Have a look at : http://blogs.microsoft.co.il/blogs/maxim/archive/2008/09/23/curiosity-killed-the-programmer-multiprocess-browser.aspx . The source of the app is in CSharp. I'm sure you can adapt it to Delphi.
Harriv, you can use a scheme based on plugins. where you have a main application and this dynamically load news functionality. There are several libraries available here I leave some.
(source: wikimedia.org)
Frameworks
TMS Plugin Framework
TJvPluginManager from JVCL
Delphi Plugin Framework
Hydra
Tutorials
Implementing Plug-Ins for Your Delphi Applications
How to make a Plugin for Your Application (Source Code)
Bye.
You can separate your application logic and execute it in several threads. That way, if one part of your application logic hangs up, you still have a responsive application. But you won't be able to put the GUI in multiple threads. The VCL requires you to execute all GUI related stuff in the main thread.
I am not sure about how Delphi operates but the standard procedure for multiprocess programming is forking.
You fork a new process with whatever code you want. Pass information to the forked process and let it run doing whatever it wants.
Can't explain multiprocess programming in one thread response. But look it up.

Call another program's functions?

So I have this program that I really like, and it doesn't support Applescript. I'd like to automate it a little bit. Now, I know that I could use applescript to tell the program to tell the menu to tell the submenu to tell the menuitem to activate or whatever, but frankly I don't like applescript very much anyway.
When I open the NIB file in IB, I can see the messages that are being sent to FirstResponder; for example, the Copy menu item sends "copy:". Is there any way for me to invoke this directly from another program?
No. It's called protected memory for a reason, you know. The other program is completely insulated from your application. There are ways to put code into other apps, but (a) it's very inadvisable (b) requires root privileges, which means the rest of your app needs to be ROCK SOLID AND IMPREGNABLE, and (c) writing such code is a black art requiring knowledge of the operating system kernel interfaces, virtual memory management, the ABI, the internals of the linker/loader, assembler programming, and the operational parameters and other specifics of the particular processor upon which your app happens to be running.
Really, AppleEvents and other such IPC mechanisms are there for a reason.
Your other alternatives (all of which are a bit hacky, to be honest, and give you the fairly significant burden of ensuring the target app is in the state you want/expect) the access the data you're looking for are:
The Accessibility APIs from the ApplicationServices framework, through which you can traverse the UI tree to grab the text from wherever you need it directly, or can activate the menu item. Access for your app has to be explicitly granted by the user, however (although this is much the same as the requirement for UI scripting).
You can use the CoreGraphics APIs (within the ApplicationServices framework again) to send keyboard events to the target application (or just to the system) directly. This would mean sending four events: Command-down, C-down, C-up, Command-up.
None of these are ideal. To be honest, your best approach would be to look at your requirements and figure out how you can best engineer around the problem by changing those requirements in some way, i.e. instead of grabbing something directly, ask the user to provide some input, etc.
You might be interested in SIMBL or in mach_inject. SIMBL is a daemon (in my fork based on mach_inject, in the original version based on injection via some ScriptingAdditions hack) which does the injection for you, so you just need to put a bundle with your code into the SIMBL directory and SIMBL will inject it for you into the target application. Or you can do so yourself via mach_inject. Or probably more convenient, mach_inject_framework which injects and runs code which just loads some framework.
I think Jim may overstate the point a bit; he's not wrong, but it seems misleading. There are lots of ways to cause a Cocoa program to execute its own code under you control (Carbon is harder). The Accessibility API is very commonly used this way (so commonly that I expect it to be repurposed eventually). Fscript can give you all kinds of access to the innards of another Cocoa program. While Input Managers may well exit the scene at some point, SIMBL is still out there today to do this kind of stuff.
Whether you like Applescript or not, Apple Events are the primary way Apple provides for inter-program control. Have you double-checked Script Editor's Open Library function to find out if the program really does have any Applescript support? You can code Apple Events entirely in Objective-C these days using Leopard's Scripting Bridge. I wrote up a tutorial if you like (it's still under-documented by Apple).
Cocoa is a reverse-engineer's dream. The same guys who host SIMBL have a nice intro to the subject. "Wolf" also writes a lot of useful information on this.
Jim's right. Many of these approaches can completely destabilize the system if done incorrectly (sometimes even if done correctly). I don't do much of this stuff on my production systems; I need them to work. But there are a lot of things you can make a Mac app do, and it's a good part of a Mac developer's training to understand how all the pieces really work.

Resources