Is there a way to unload bundle after mach_inject - macos

I want to load the newer version of bundle to the target process but it's impossible because the bundle with same name already loaded. Changing CFBundleVersion or CFBundleShortVersionString of bundle doesn't work. The easiest way to do it is simply kill the target process and restart it. But I don't think that it's a best way to do it. So is there another way to do it?

I am facing the same problem with mach_inject. I don't see a straight forward solution without modifying mach_inject.
My solution is to create two bundles. Consider the 1st bundle to be a plugin manager for the real plugin. The plugin manager is very simple and hopefully never needs to be upgraded, it loads and unloads the original bundle with cleanup code added.
I am using Apple's NSBundle class to load and unload the plugin. Before unloading I call the principal class in the original plugin to have it clean up.
Unloading bundles written in objective C is dangerous. 2 & 4 are true in general.
Mach_override can not be undone, but can be called in the plugin manager and call code in the real plugin.
Categories and protocols are not safe to use in plugins meant to be unloaded.
You need to un-swizzle what you swizzled, and remember you can not remove methods, so when you reload the plugin, you need to replace (not add) the old dangling methods. You will need to check your swizzle code.
You need to invalidate timers installed, remove observers, and remove anything else added to the run loop.

Related

How do you reset or reimport, plugins, in Unity / Mac?

Get a Unity project with a native low-level plugin .. Mac version.
Make a small change in the Xcode plugin project, and build.
You now have the new plugin library in the Unity project.
If you "Build" again, the final Mac app of course now contains the new library - no problem.
However .....
if you hit Play in the Editor,
it does not pick up the change in the library.
In fact it seems:
Every time you change a library in Unity, you must restart Unity!
Everything has been tried, "Reimport all assets", AssetDatabase.Refresh, renaming, etc etc. It seems you literally must restart Unity.
What's the deal on this?
More information on this:
It would seem that mac shared libraries/bundles cannot be unloaded. Article:
https://docstore.mik.ua/orelly/unix3/mac/ch05_03.htm
Apparently this was fixed in 10.5:
https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlclose.3.html
Maybe Unity could solve this now. At their usual pace it should happen anytime around 2035.
Sadly it comes down to you can't do anything about it.
As per .net's DLL handling DLL's cannot be unloaded individually without closing the application domain. And while Unity picks up the changes done to the DLL the old version is kept in memory and used at runtime in the editor. A "funny" thing you can do to see this in action is by deleting the native plugin from within the editor. Confirm that you want to delete the file. The file will dissapear from the inspector. However if you right click the folder and refresh (ctrl+r) you will see that the file gets reconstructed (this also happens when hitting "re-import all", as the application domain isn't closed, despite unity restarting).
When building the application it will however use the locally stored file, and not the memory stored file. Hence the plugin being updated on the build.
There is no way to unload an individual assembly without unloading all of the application domains that contain it. Even if the assembly goes out of scope, the actual assembly file will remain loaded until all application domains that contain it are unloaded.
source
This has been a problem for some time now, and people have made attempts for work arounds and/or fixes, but as far as I am aware the "work arounds" that exist now are for windows only. here are some links to discussions about it.
"Unload a plugin"
"Reloading native plugins"
I suppose something that could be done is writing a wrapper that automatically restarts Unity when the dll has been edited... Although this won't solve the issue it'll atleast make it somewhat less of a hassle.

What happens if I edit a framework code in Xcode that was added using pods?

I added a framework to my project in Xcode written in Swift. There was some issue in the framework so I tried to modify and a dialog came out giving me the option to lock or unlock, so I choose Unlock and proceed.
Would it harm the owner? Would these changes continue with my project until my app is in the App Store? Please let me know if there is an issue with that and help with a solution.
Simply I need all framework files but I don't need all functions. In addition, I need to add functions to fit to my project.
It is not recommended to modify a third party pod's code, as it will be overwritten with the next pod update.
There are multiple solutions you can try:
implement the framework manually and modifying it there (keep in mind that you are losing the capability of quick updating)
modify it as an extension of the framework if possible, i. e. store your changes in a separate file and paste it everytime an update occurs (not recommended as it is not too convenient)
fork the project and make changes on that separate fork
create a pull request to the project that includes the modifications (if you think they are helpful for others as well)

How to automatically update OSGi framework bundles list at runtime?

Here is the context: I have 2 osgi products running, one which is the main software (lets call it 'software') and the other which manages updates/installs/uninstalls of the first one, using p2. (lets call the second one 'updater')
I managed to make the updater install a feature into the software, meaning that the feature was successfully installed in the features directory and its bundles in plugins directory. Regarding p2 everything is good, the profile is updated with the new changes.
However it had absolutely no effect on the software, which didn't care of the new feature.
So I added some p2.inf files in my plugins with the instruction installBundle and this made my new bundles being added in the config.ini file which contains the list of bundles to load.
This makes me very close to the victory because when I restart the software, my new plugins are loaded by the framework. But.. I don't want to restart and I'm not supposed to have to since osgi is able install stuff in live.
Still fighting, my searching made me discover the simpleconfigurator which is responsible of loading the list of bundles from a file and giving them to the framework which will do everything it needs. But it does it only at the startup and I don't find any way or any doc to ask him to do refresh the list at runtime.
The only solution I've done so far is to call the update() method on the bundle org.eclipse.equinox.simpleconfigurator and then my bundles get recognized and work perfectly.
So right now, I have something working but I'd like to find a better solution and the reason that I'm telling the full story is because I'm surprised by the fact that, after battles with p2, I also need to fight with osgi to make it loading the new bundles..
Thanks for any help :)
I am not very familiar with p2. But it sound like you have two problems - you need some way to programatically deploy bundles into the OSGi container at run time and have the main application be aware of and use the functionality from those bundles.
For the first problem take a look at the selected answer on Programmatically Start OSGi (Equinox)?
For the second part you can use a ServiceListener - http://www.osgi.org/javadoc/r4v43/core/org/osgi/framework/ServiceListener.html - in your main application to listen for Services that implement a pre-defined interface. You main application should get notified whenever services are REGISTERED or UNREGISTERED at run time and can react accordingly.
you can find your bundle, and invoke bundle.update(InputStream input).
http://www.osgi.org/javadoc/r4v43/core/org/osgi/framework/Bundle.html#update(java.io.InputStream)

How to check if an extension is really used in Joomla

I want to know if a extension (for example: joomfish) is really used or not used at all before i disable it / uninstall it.
Is there a way to check ?
First, in Joomla plugin has a specific meaning, so what you want to know is whether a component, module or plugin is used.
This is a common problem when you inherit sites. A lot of times users install tons of extensions and never use or uninstall them.
The simplest first step with modules and plugins is to see if they are published or not. Also you can look at modules and see if they are assigned to any positions or menu items.
In terms of extensions, if they are a kind of extension that would be used to create content and you look at the manager you can see if any content was ever created. If not it is probably safe to uninstall. IF there is content then you will want to figure out whether you need o preserve it.
The problem with Mike's answer is .. how do you know if you have tried every possible combination of things or possible events with enough certainty to say for sure that something is not running ever. For example you may have a component that you never use as a menu item but then some module is running a query against its data.
Well you cannot know that. To be absolutely shure you could write a system plugin which gets triggered on plugin calls and logs the triggering plugin names.

TYPO3 extensions and symlinks

Can I create a symlink to the local extension from aonther project folder? I have a common local-server and i need to implement same extension on all local project-installations. I tried to put the symlink, but some times i do not get expected output. I get it only after clearing the cache of that perticular project.
Your scenario is a common one I guess. But as Omar said, linking to the same code base of the extension through several typo3 instances is not a good practice.
But we have the same structure as yours, we realize this through SVN. All of our projects got a SVN repository and common extensions have their own repository. Through svn:externals the extensions are linked into the concrete project. This has the advantage that you can change the extension in the concrete project and after committing all other projects (that do have to update from svn though) contribute from it. I Think this would fit your needs, too.
If I understand your question correctly you have several Typo3 sites on the same server and want to share an extension between them using a symlink. I don't think that is a very great idea because many extensions use tables and every site normally has it's own database so you would have to do a lot of tinkering to get that to work.
Instead you could make all the modifications to the extension files in the typo3conf/ext/extension_name folder and then export the extension to a t3x file (Ext Manager in the Backend). This t3x file can be installed as a extension (Import extension) on all your other sites.
If you extension does not use a database and you are planning to make frequent changes then I guess you should be able to make that work (the symlink). Otherwise I recommend you use the first approach I described.
I have not tried this, but you should be able to install extensions globally in Typo3. What this means is that the given extension is placed inside '(typo3_src/)typo3/ext/' instead of 'typo3conf/ext/', presuming both sites use the same Typo3 Core/Source (and thus typo3_src is a symlink to the location of the core).
You can enable installing global extensions via the Install Tool. Once inside the tool, click on 'All Configuration', then search for allowGlobalInstall. Or put the following line into your localconf.php:
$TYPO3_CONF_VARS['EXT']['allowGlobalInstall'] = '1';
At last, but not least, you need to make sure the 'typo3/ext/' directory is writeable.
Hope this will be to some help. If you have any further questions, let me know :)
As Björn mentioned, I'd sugegst to install them globally. Mind you, updating the source will require to move the extensions accordingly..
As for "expected output": be aware that the code in these folders is cached in various ways (mainly page content and config settings), and hence not always run. This is the reason a change done from "outside" the current installation is likely not to propagate to your output without clearing these caches (as you have observed).
When you actually install an extension via the extension manager, the cache should (if correctly configured) be cleared (interested parties may search for clearCacheOnLoad in class.em_index.php to reveal a clear_cacheCmd('all')). There is a small checkbox, which is normally checked, during the installation process to accomplish this.
Omar's first approach is therefore, as I see it, the more easy way to get "expected output" and less jumbling around with global extensions.

Resources