Even when I just use the Window-based application template, which does literally nothing, instruments (activity monitor) says my application's process is using 8.14MB of Real Memory! Even with this method:
void report_memory(void) {
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kerr = task_info(mach_task_self(),
TASK_BASIC_INFO,
(task_info_t)&info,
&size);
if( kerr == KERN_SUCCESS ) {
NSLog(#"Memory in use (in bytes): %u", info.resident_size);
} else {
NSLog(#"Error with task_info(): %s", mach_error_string(kerr));
}
}
Its still ~8.14 MB! So it seems that instruments is right, but why would a UIWindow take up that much memory??
My guess would be that it's the Objective-C runtime libraries that are taking up all that space, rather than your UIWindow itself. However, all applications use a copy of these libraries, the iPhone OS may be smart enough to share that memory among all of the applications that are running (although of course, only system apps are allowed to run in the background).
Related
I'm developing character devices for a Linux kernel distro Poky 1.7 built with Yocto and installed on a Freescale imx6sx target board. They're simple modules, that are just used to read/write IO registers of the SoC.
Everything has worked well till I've load the modules after login, by simple calling in the target console
modprobe mydevice
Problems have begun since I've automatically load this modules at boot time. First time system startup after flashing my board, my custom modules are loaded and I can open them, do read/write operations...therefore they're working.
Restarting the system (switching it off and on or rebooting), modules are still loaded, but I'm unable to use them.
After some trials, what I've seen is that the problem is dynamic allocation of the device number they use, in particular function alloc_chrdev_region( ) called in the __init( ) function of the module.
In fact, really first time the system is switched on after has been flashed, the device file's device number in /dev is up-to-date with the /sys/class/myclass/mydevice/dev device number, while from the first reboot they doesn't match anymore. Briefly:
First boot:
/dev/mydevice device number [Major, Minor] = 247,0
/sys/class/myclass/mydevice/dev device number [Major, Minor] = 247,0
Second and later boots:
/dev/mydevice device number [Major, Minor] = 247,0
/sys/class/myclass/mydevice/dev device number [Major, Minor] = 248,0
So, it seems like the device file is kept in memory instead of been updated at every boot.
Here is main code for __init( ) and __exit( ) functions:
static struct class *g_deviceClass;
static struct cdev g_characterDevice;
static dev_t g_deviceNumber;
static int __init npe_power_drv_init(void)
{
int32_t result;
if ( alloc_chrdev_region(&g_deviceNumber, 0, 1, DEVICE_NAME) < 0 )
{
return -EAGAIN;
}
cdev_init(&g_characterDevice, &npe_power_drv_ops);
g_deviceClass = class_create(THIS_MODULE, CLASS_NAME);
if( device_create(g_deviceClass, NULL, g_deviceNumber, NULL, DEVICE_NAME) == NULL )
{
class_destroy(g_deviceClass);
unregister_chrdev_region(g_deviceNumber, 1);
return -EAGAIN;
}
result = cdev_add(&g_characterDevice, g_deviceNumber, 1);
if( result < 0 )
{
device_destroy(g_deviceClass, g_deviceNumber);
class_destroy(g_deviceClass);
unregister_chrdev_region(g_deviceNumber, 1);
return -EAGAIN;
}
return 0;
}
static void __exit npe_power_drv_exit(void)
{
device_destroy(g_deviceClass, g_deviceNumber);
class_destroy(g_deviceClass);
cdev_del(&g_characterDevice);
unregister_chrdev_region(g_deviceNumber, 1);
}
module_init(npe_power_drv_init);
module_exit(npe_power_drv_exit);
Using static device number allocation, register_chrdev_region( ) everything works fine. Sure I can use this latter way to implement my code, but I would like to know why I've got this behaviour.
Many thanks for any help
Andrea
Sorry if it was asked before, but I can't really google any.
I was trying to read files within the KEXT of OSX, using vnode_open() like the following:
struct vnode *vp = NULL;
kern_return_t kret;
vfs_context_t ctx = vfs_context_current();
kret = vnode_open(path, FREAD, 0, 0, &vp, ctx);
if (kret != KERN_SUCCESS) {
// Error log
} else {
proc_t proc = vfs_context_proc(ctx);
kauth_cred_t vp_cred = vfs_context_ucred(ctx);
char *buf = NULL;
int resid;
int len = sizeof(struct astruct);
buf = (char *)IOMalloc(len);
kret = vn_rdwr(UIO_READ, fvp, (caddr_t)buf,
len, 0, UIO_SYSSPACE, 0, vp_cred, &resid, proc);
vnode_close(fvp, FREAD, ctx);
if (kret != KERN_SUCCESS) {
// Error log
}
// Do something with the result.
}
vfs_context_rele(ctx);
Once the kext was loaded, the system panics and reboots. As long as vnode_open() is there, it panics.
Am I doing it wrong?
One thing that immediately stands out:
You shouldn't be using vfs_context_current() - use vfs_context_create(NULL). What's worse, you're subsequently calling vfs_context_rele(ctx); on the returned context. Only vfs_context_create retains, vfs_context_current() does not, so you're over-releasing the VFS context. This could certainly cause a kernel panic.
In general, when developing kexts, you can really be doing a lot more than just letting the system reboot after a kernel panic:
Panic logs are written to NVRAM, and on next boot, are saved to file. You can inspect them via Console.app, under "System Diagnostic Reports" starting with "kernel".
Panic logs contain a stack trace, which is by default unsymbolicated. You can symbolicate them after the crash, but it's a lot more convenient to set the keepsyms=1 boot argument and get the crash handler to symbolicate for you.
You can set up the debug boot argument to make crashes initiate the kernel debugger or core dumps, write the stack trace to serial/firewire console, etc.
These things are documented in part on Apple's site, but a bit of searching on the web might get you some more detailed information. In any case, they're incredibly useful for debugging problems like this.
Is there a Windows API to detect if a laptop lid is closed (= integrated laptop screen is off)?
There's already the "same" question asked:
Get current laptop lid state
Though the (self-)accepted answer relies on an integrated screen "device" being removed, when the lid closes. But that does not happen on all laptops. Some keep the screen "available" to the system (while not displaying anything actually), even when the lid is closed. This means that the Windows desktop still stretches over the closed screen (if the "Multiple Displays" settings is set to "Extend these displays").
I have not determined yet, if this behavior can be configured or if it is driver-specific:
Remove closed laptop screen from Windows desktop
But even on such systems, the OS knows that the lid closes, as it can shutdown/sleep the machine when it does. And it broadcasts a notification (WM_POWERBROADCAST):
Detect laptop lid closure and opening
Background: I have an application that starts on the same display, where it was closed the last time. If it was closed on the integrated laptop screen and the lid is closed the next time the application starts (because the user is now using an external monitor), my application starts on the now-invisible integrated laptop screen.
Hence I want to detect that the lid is closed and force the application onto an external monitor.
So I'm looking either for a way to detect, if lid is closed. Or for a way to detect, that a particular screen is off (what would be a cleaner solution).
Sounds like you don't really care if the lid is closed or not and just want to know if the screen area where you are about to launch your application is available or not.
If the OS "still uses the shut off screen for its extended desktop" then that means (from the OS's point of view) that the screen is available to be used for applications. In other words - your application would not be the only one suffering from that issue. Though I have to say I have never observed that particular behavior first-hand.
If you need to move your application while it is running then you can register for the RegisterPowerSettingNotification and act on it.
However if you are launching and need to know if the screen is on or off you have two options:
EnumDisplayDevices
This will provide you with the information on whether your screen is attached to a desktop and is active. This is "system info" that you get from the API in User32.dll
DISPLAY_DEVICE ddi;
ddi.cb = sizeof(ddi);
DWORD iDevNum = 0; // or iterate 0..15
EnumDisplayDevices(NULL, iDevNum, &ddi, /*EDD_GET_DEVICE_INTERFACE_NAME*/0);
if( (ddi.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) == 0 &&
(ddi.StateFlags & DISPLAY_DEVICE_ACTIVE) != 0 ){...}
DXGI (DX11)
This gives you basically the same info as above but with a more modern approach (and potentially fewer false positives). Of course that would require you to link-in DXGI for this to work and include the header which will increase your application size:
#include <atltypes.h>
IDXGIAdapter * pAdapter;
std::vector <IDXGIAdapter*> vAdapters;
IDXGIFactory* pFactory = NULL;
// Create a DXGIFactory object.
if(FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory) ,(void**)&pFactory)))
{
return;
}
for(UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i){
DXGI_ADAPTER_DESC ad = {0};
if(SUCCEEDED(pAdapter->GetDesc(&ad))){
UINT j = 0;
IDXGIOutput * pOutput;
while(pAdapter->EnumOutputs(j, &pOutput) != DXGI_ERROR_NOT_FOUND)
{
DXGI_OUTPUT_DESC od = {0};
if(SUCCEEDED(pOutput->GetDesc(&od))){
// in here you can access od.DesktopCoordinates
// od.AttachedToDesktop tells you if the screen is attached
}
pOutput->Release();
++j;
}
}
pAdapter->Release();
}
if(pFactory)
{
pFactory->Release();
}
Hope that helps.
Direct3D9
This method also provides display information but in a slightly different way - via a list of adapters and monitors attached to those adapters. Remember to link-in d3d9 library for this to work:
void d3d_adapterInfo(IDirect3D9 * _pD3D9, UINT _n)
{
D3DADAPTER_IDENTIFIER9 id;
const DWORD flags = 0;
if(SUCCEEDED(_pD3D9->GetAdapterIdentifier(_n, flags, &id))){
// id provides info on Driver, Description, Name
HMONITOR hm = _pD3D9->GetAdapterMonitor(_n);
// and based on that hm you get the same monitor info as
// with the first method
}
}
void d3d_enumDisplays()
{
cout << endl << "--- Information by Direct3D9 ---" << endl;
IDirect3D9 * pD3D9 = Direct3DCreate9(D3D_SDK_VERSION);
const auto nAdapters = pD3D9->GetAdapterCount();
cout << "A total of " << nAdapters << " adapters are listed by Direct3D9" << endl;
for(UINT i = 0; i < nAdapters; ++i){
d3d_adapterInfo(pD3D9, i);
}
pD3D9->Release();
}
All 3 code snippets are from some of my projects so you can just copy-paste the code and it should work (baring some minor fixes for missing functions or variables as I was modifying the code on-the-fly to reduce its size when posted it here)
I'm trying to change my process' name as it appears in ps and Activity Monitor at runtime. I found several notes that there is no portable way to do this (which I don't care about).
Here's what I tried. None of these approaches worked for me.
Changing argv[0] (seems to be the way to go on some Unix systems)
Calling [[NSProcessInfo processInfo] setProcessName:#"someName"]
Calling setprogname (calling getprogname returns the name I set, but that is irrelevant)
I also read about a function called setproctitle which should be defined in stdlib.h if it is available, but it's not there.
There must be a way to accomplish this because QTKitServer - the faceless decoder for QuickTime Player X - has its corresponding QuickTime Player's PID in its process name.
Does anybody have a clue about how to accomplish this? I'd very much prefer a Core Foundation or POSIXy way over an Objective-C method to do this.
Thanks,
Marco
Edit: If it is in any way relevant, I'm using Mac OS X 10.6.5 and Xcode 3.2.5
There are good reasons to change the process name. Java software should change process names because when running different java tools I want to see which java process is for which tool.
Chromium does it: http://src.chromium.org/viewvc/chrome/trunk/src/base/mac/mac_util.mm.
Node.js uses same code to implement Process.title = 'newtitle': https://github.com/joyent/node/blob/master/src/platform_darwin_proctitle.cc
Note: This fails if someone does su to a different not logged-in user: https://github.com/joyent/node/issues/1727
Here the source code in its full complex glory. By the way, someone told me it also works for Mac OS X Lion and also fails with su.
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
void SetProcessName(CFStringRef process_name) {
if (!process_name || CFStringGetLength(process_name) == 0) {
NOTREACHED() << "SetProcessName given bad name.";
return;
}
if (![NSThread isMainThread]) {
NOTREACHED() << "Should only set process name from main thread.";
return;
}
// Warning: here be dragons! This is SPI reverse-engineered from WebKit's
// plugin host, and could break at any time (although realistically it's only
// likely to break in a new major release).
// When 10.7 is available, check that this still works, and update this
// comment for 10.8.
// Private CFType used in these LaunchServices calls.
typedef CFTypeRef PrivateLSASN;
typedef PrivateLSASN (*LSGetCurrentApplicationASNType)();
typedef OSStatus (*LSSetApplicationInformationItemType)(int, PrivateLSASN,
CFStringRef,
CFStringRef,
CFDictionaryRef*);
static LSGetCurrentApplicationASNType ls_get_current_application_asn_func =
NULL;
static LSSetApplicationInformationItemType
ls_set_application_information_item_func = NULL;
static CFStringRef ls_display_name_key = NULL;
static bool did_symbol_lookup = false;
if (!did_symbol_lookup) {
did_symbol_lookup = true;
CFBundleRef launch_services_bundle =
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
if (!launch_services_bundle) {
LOG(ERROR) << "Failed to look up LaunchServices bundle";
return;
}
ls_get_current_application_asn_func =
reinterpret_cast<LSGetCurrentApplicationASNType>(
CFBundleGetFunctionPointerForName(
launch_services_bundle, CFSTR("_LSGetCurrentApplicationASN")));
if (!ls_get_current_application_asn_func)
LOG(ERROR) << "Could not find _LSGetCurrentApplicationASN";
ls_set_application_information_item_func =
reinterpret_cast<LSSetApplicationInformationItemType>(
CFBundleGetFunctionPointerForName(
launch_services_bundle,
CFSTR("_LSSetApplicationInformationItem")));
if (!ls_set_application_information_item_func)
LOG(ERROR) << "Could not find _LSSetApplicationInformationItem";
CFStringRef* key_pointer = reinterpret_cast<CFStringRef*>(
CFBundleGetDataPointerForName(launch_services_bundle,
CFSTR("_kLSDisplayNameKey")));
ls_display_name_key = key_pointer ? *key_pointer : NULL;
if (!ls_display_name_key)
LOG(ERROR) << "Could not find _kLSDisplayNameKey";
// Internally, this call relies on the Mach ports that are started up by the
// Carbon Process Manager. In debug builds this usually happens due to how
// the logging layers are started up; but in release, it isn't started in as
// much of a defined order. So if the symbols had to be loaded, go ahead
// and force a call to make sure the manager has been initialized and hence
// the ports are opened.
ProcessSerialNumber psn;
GetCurrentProcess(&psn);
}
if (!ls_get_current_application_asn_func ||
!ls_set_application_information_item_func ||
!ls_display_name_key) {
return;
}
PrivateLSASN asn = ls_get_current_application_asn_func();
// Constant used by WebKit; what exactly it means is unknown.
const int magic_session_constant = -2;
OSErr err =
ls_set_application_information_item_func(magic_session_constant, asn,
ls_display_name_key,
process_name,
NULL /* optional out param */);
LOG_IF(ERROR, err) << "Call to set process name failed, err " << err;
}
Edit: It's a complex and confusing problem.
On OS X there is no setproctitle(3). One has to write into the argv array (ugly
and a bit dangerous because it is possible to overwrite some environment variables with bogus stuff). Done correctly it works very well.
Additionally Apple has the ActivityMonitor application, something like the Task Manager under Windows. The code above manipulates ActivityMonitor but this manipulation doesn't seem to be encouraged by Apple (hence the use of undocumented functions).
Important: ps and ActivityMonitor don't show the same information.
Also important: ActivityMonitor is not available if you don't have GUI. This can happen if you ssh in to a remote Apple box and there is nobody logged in by GUI. Sadly there is a bug by Apple IMO. Just querying if there is a GUI sends an annoying warning message to stderr.
Summary: If you need to change ActivityMonitor, use the code above. If you have GUI-less situations and and dislike warnings on stderr, redirect stderr temporarily to /dev/null during the call of SetProcessName. If you need to change ps information, write into argv.
You can use the lsappinfo tool which comes with macOS since at least 10.6 and up to present day (10.13.2):
Shell:
lsappinfo setinfo <PID> --name <NAME>
C++:
#include <sstream>
#include <string>
#include <stdlib.h>
void setProcessName (pid_t pid, std::string name)
{
std::ostringstream cmd;
cmd << "/usr/bin/lsappinfo setinfo " << pid;
cmd << " --name \"" << name << "\"";
system (cmd.str().c_str());
}
Is there a programmatic way to find out what architecture another process is running as on Mac OS X 10.5 and later?
Examining the process's image file is not a solution, as the image is likely to contain multiple architectures, and between arch(1) and the “Open in Rosetta” and “Open in 32-bit mode” checkboxes, there's no way to tell from the image alone which architecture is actually running.
Can you use NSRunningApplication on OSes where it is available, and fall back to sysctl stuff when it isn't? I don't think sysctl stuff is supportable API the way most stuff is, but if you're only using it on old OSes you should be okay.
Try this to get the CPU type of the process:
cpu_type_t cpuType
size_t cpuTypeSize;
int mib[CTL_MAXNAME];
size_t mibLen;
mibLen = CTL_MAXNAME;
err = sysctlnametomib("sysctl.proc_cputype", mib, &mibLen);
if (err == -1) {
err = errno;
}
if (err == 0) {
assert(mibLen < CTL_MAXNAME);
mib[mibLen] = pid;
mibLen += 1;
cpuTypeSize = sizeof(cpuType);
err = sysctl(mib, mibLen, &cpuType, &cpuTypeSize, 0, 0);
if (err == -1) {
err = errno;
}
}
And test CPU_ARCH_ABI64 to check for 64-bit.
You don't say what your requirements are, but the NSRunningApplication class introduced in 10.6 offers a really easy interface for this. The docs are currently a little off, but it is there.