Some tricks in passing file descriptors through unix domain socket

Passing file descriptors through unix domain socket is well-known. But there still have some tricks in implementation. I spent one day to deal with it in Mac OS X by digging into xnu source.

  1. How to pass multiple file descriptors in one sendmsg() call>

    Simple. Put all file descriptors one by one after struct cmsghdr.

  2. Can I put multiple struct cmsghdrs with data? I noticed there are CMSG_FIRSTHDR() and CMSG_NXTHDR() defined in <sys/socket.h>

    No. In xnu sources it checks msghdr.controllen with cmsghdr.cmsg_len. If they are not equal, a -EINVAL returned in sendmsg() call. That means only one cmsghdr can be put into msghdr.

The limitation is in OS X only. I haven’t check Linux and would do it soon or later.

Some license checkpoints in Reveal app.

  1. [IBAAppDelegate applicationDidFinishLaunching:] would call [IBAAppDelegate verifyCodeSignature] to verify code signature of the app to prevent itself from modifications.
  2. [IBATrialModeReminderPresenter shouldShowTrailModeSheet] controls whether trial mode sheet, including quit after trial period expired, would be shown.
  3. [IBAMainWindowController configureTitleBarAccesoryView] will create IBATrialModeReminderTitleBarAccessoryView to shown trial information on window’s title bar.

That’s all.

Make IB designed view work with iCarousel

Oddly, View designed in IB would have FlexibleWidth+FlexibleHeight set in it autoresizingMask, even if you cleared everything in auto resizing box, regardless using AutoLayout or not. The behavior causes that subviews inside item view have wrong positions after transform3D with rotations. In short, item view’s width/height in subviews position/constraints calculation would be calculated as rotated value instead of  preset value, 

The solution is put self.autoresizingMask = 0 to awakeFromNib, easiest? But it took me 1.5 days to find the reason.

Just found 2 issues in apple’s assembler for arm64

1) The classic ‘@‘ comment indicator is not recognized in -arch arm64 mode. Both ‘;‘ and ‘//‘ are permitted. I remembered ‘@‘ was acceptable in armv7 age. So the world changes so fast…

2) As ARM’s instruction reference manual, the instruction ‘movi‘ has a format as

MOVI Vn.<T>, #uimm8{, LSL #shift}

But as reported error if we omitted last part. So to make assembler work, I have to append a ‘LSL #0’ to the end. Feel somewhat stupid, for both the assembler and myself 🙂

Android SurfaceView: can be used for media or direct access, but not for both.

That is, if you have an instance of SurfaceView, you can use it for video/camera, or use it for direct access as a buffer, but you cannot reuse it for media after you already accessed it through either ANativeWindow API or any other internal ways.

The reason is in ASOP code Surface.cpp. Surface connected to CPU if it once got locked, which is a necessary step to access its internal buffer. But it only got disconnected in  destructor. On other side, if you bind the Surface to media, it checks the connection status and return an error when it found it has already been connected to CPU.

So, if you need a SurfaceView for both purpose, you have to destroy the old, assuming it is for direct access, and create a new one for media.

So many traps there…

Simply, a .so compiled by android ndk r9 gcc 4.6 crashed on loading in function __check_for_sync8_kernelhelper.

After looking up the issue in Google, I found this issue has been reported to Google: https://code.google.com/p/android/issues/detail?id=58476. Unfortunately no solution at present.

Basically it is an libgcc issue depending on linux kernel version. Lower kernel version lacks the symbol that libgcc in 4.6 or higher needs. For example, the Galaxy Nexus I am just testing app on.

 

So,

1) Avoid using 64bit atomic operation built in gcc, if you can control everything in your codes.

2) Using gcc 4.4.3. For ndk r9 there is a legacy toolchain package in a separated download link.

Why so many latencies in BB10 audio playback? Why we always get underrun in audio data feeds?

They are two faces of one same issue.

If you started coding audio playback from reading PlayWav sample in BlackBerry’s github repository, you will find there are long latencies in audio playback, that is, about 5s after you fed data, you can hear the sound. But why? BB10 uses ALSA’s libasound as its audio API but the documentation and description are very little. So after many changes here and there, many trials and inspections, I got what controlled the latency.

snd_pcm_channel_params_t.buf.block.frag_max;

In PlayWav sample, this field is set to -1, which returned a large number in it from call of snd_pcm_plugin_params(). So we can set this field to a small number to reduce the latency. Indeed it is said that RIM recommends 5 but I don’t know whether it is true and I cannot remember where I found it.

Anyway, a number like 3 or 5 can exactly reduce latency to some small value so that our ears cannot find it. But another strange behavior occurs then: we got UNDERRUN frequently. At that time, if we set snd_pcm_channel_params_t.stop_mode to SND_PCM_STOP_STOP, the playing back stopped after a short time interval; if we set snd_pcm_channel_params_t.stop_mode to SND_PCM_STOP_ROLLOVER, the playback will repeats data in a few last buffers.

The latter issue is due to thread priority. QNX’s io-audio drivers runs playing back in very high priority so it is very easy to make your data UNDERRUN if you just run your data feed thread in a normal priority. In some discussion somebody recommends set data feed thread to 50 and in some other codes the value was set to 18 or so.

Conclusion: to make audio playback smoothly and easily, 1) set frag_max to 5 or another small value but too small may cause UNDERRUN issue. The field controlled data buffering – yes, it equals to audio latency on other side – in implementation of audio playbacks. 2) raise your data feed thread priority to some higher value. Normal thread runs on 10 and audio playback thread runs on a higher priority. Set to higher to avoid data UNDERRUN.

 

iOS7: We cannot modify UIAlertView directly now.

From iPhoneOS 1 to 6, each experienced iOS programmer knows how to modify UIAlertView for appearance customization. For example, to add some UI elements like UILabel or a secure UITextField for password input, etc. One of our little tool keyOne used this trick.

But this doesn’t work in recent iOS7 beta. The reason is simple after checking view hierarchy in debugger. This is keyWindow when a UIAlertView popped up:

(lldb) po [[UIApplication sharedApplication] keyWindow]
<_UIModalItemHostingWindow: 0xb2dba70; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0xb2d5f20>; layer = <UIWindowLayer: 0xb2dbb50>>

and a view for alert exactly

(lldb) po [[[[[UIApplication sharedApplication] keyWindow] subviews] objectAtIndex:1] subviews]
<__NSArrayM 0xc975e80>(
<UIView: 0xb2e83a0; frame = (0 0; 320 568); layer = <CALayer: 0xb2e8770>>,
<_UIModalItemRepresentationView: 0xb2e5de0; frame = (25 184; 270 200); layer = <CALayer: 0xb2e5da0>>
)

The UIAlertView returned to caller is a stub only

lldb) po alertView
<PasswordPrompt: 0xb2c7f80; baseClass = UIAlertView; frame = (0 0; 0 0); opaque = NO; layer = <CALayer: 0xb2a1cc0>>

The view has zero size so we certainly cannot customize it.

 

It is just like walking on a steel wire over the deep…

…to play with Apple’s famous Xcode and LLVM compiler sets, especially for ARM instead of x64 series.

So, somebody may ask: What beats you on the face _again_?

This time Apple decided to use clang 4.0 from LLVM 3.1svn in its latest Xcode 4.4, which was just pushed out with Mountain Lion some days ago. That’s OK. Generally most of things still work, most of codes still got compiled. But, suddenly I found an assembling error on my one .S file: invalid instruction ‘ldmltfd’. It is not the exact error message but you know the meaning is it.

The .S file can be compiled/assembled without any problem by previous Xcode version, if my memory is still correct, at least by any version of Xcode 4.x and its toolchains, from apple-gcc-4.2 to clang. And, ‘ldmltfd’ is a valid ARM instruction. So it should be another LLVM/clang’s issue. Indeed I must not feel surprising since I already encountered many before.

But I must have a work around otherwise I must return back to Xcode 4.3.x, which doesn’t have official ML support in it. Though I think it is not a big problem, the uninstall and install still take much time. OK. Let’s see.

After adding ‘-v’ to compiling option the output shows clang called itself with ‘-cc1as’ after executed preprocessing. ‘clang -cc1as –help’ shows this call invokes clang’s integrated assembler to assemble the source instead of invoking external ‘as’ program. Fortunately ‘clang’ in my Lion system is still an old version (3.1 from LLVM3.1svn) so I can check it over the source with ‘-v’ option and found it invokes external assembler.

The issue is clear now. Apple guys or LLVM guys or guys having both roles thought clang’s integrated assembler is stable and complete enough. They released this version of clang with integrated assembler set as default behavior in Xcode 4.4. I am just this unlucky man stepping on the mines.

Solution is always simple as long as clang permitted us disable its integrated assembler. Adding ‘-no-integrated-as‘ to each .S file solved the issue, but it still took me about 1 hour to look for the cause and about half an hour to write this blog.