Issue launching X11 app via NSTask

為{幸葍}努か 提交于 2020-03-05 07:29:17

问题


My app uses NSTask to execute shell scripts, one of those scripts launches an X11 app (specifically meld).

I would have expected this to work:

#!/bin/bash
source ~/.profile                      # setup $PATH/etc
meld .

But it fails with:

gtk.icon_theme_get_default().append_search_path(meld.paths.icon_dir())
Traceback (most recent call last):
  File "/usr/local/bin/meld", line 132, in <module>
    gtk.icon_theme_get_default().append_search_path(meld.paths.icon_dir())
AttributeError: 'NoneType' object has no attribute 'append_search_path'

As a proof of concept I changed the script to this, which works perfectly:

#!/usr/bin/ruby

exec 'osascript -e \'tell app "Terminal" to do script "meld ' + Dir.pwd + '" in front window\''

Does anyone what is causing the problem? Here is my code for executing the shell script:

NSTask *task = [[NSTask alloc] init];
task.launchPath = self.scriptURL.path;
task.standardOutput = [NSPipe pipe];
task.currentDirectoryPath = workingDirectoryURL.path;

[task launch];

回答1:


X11 apps learn the display server's address using the DISPLAY environment variable.

On OS X, the DISPLAY value is randomized for security reasons, so you can't hard-code it, as you noticed. Instead, there is a launchd agent that tells launchd to set DISPLAY when it starts a process.

Somewhere between launchd and meld, the value of DISPLAY is being dropped or overwritten. Your job is to find out where.

  1. Make sure the launchd agent is running. Run launchctl list and look for org.macosforge.xquartz.startx. Since meld is working from Terminal.app this part is probably correct.
  2. Make sure DISPLAY is set in your app. It should be listed in [NSProcessInfo processInfo].environment.
  3. Make sure DISPLAY is set in the NSTask you launch. Try running /usr/bin/env with an NSTask, and make sure DISPLAY appears in its output.
  4. Make sure DISPLAY is set inside the script you run. Try echo $DISPLAY before and after sourcing ~/.profile. (Sometimes the .profile itself overwrites DISPLAY to an incorrect value because that's sometimes the right thing to do on other operating systems.)

EDIT: this is the code I used to copy DISPLAY from my GUI app to the shell script:

NSTask *task = ...
task.environment = [NSProcessInfo processInfo].environment;
[task.launch];



回答2:


Change your script to spew the environment variables and compare "working" to "not-working".

There are subtle differences between how shells are initialized across the different execution models. Almost assuredly, the environment is the source of your issues.




回答3:


Take a look at man launchctl

launchctl submit ... -p /usr/local/bin/meld -- .

to have launchd launch the job; that will set certain environment variables for you that are part of the per-user session.



来源:https://stackoverflow.com/questions/15650151/issue-launching-x11-app-via-nstask

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!