Cocoa/OSX 控制台消息:无法设置 Mach 任务特殊端口 9:(os/kern) 无法访问

发布于 2024-11-03 19:36:48 字数 842 浏览 1 评论 0原文

我有一个数据收集应用程序(地球磁场强度),有四个阶段;它们通过 cron 以 2、3、4 和 5 分钟的间隔运行,并进行排序,以便在某一步骤发生之前收集到一步所需的所有内容。

由于间隔的原因,据我所知,我无法使用 launchd 来触发阶段;因此,我使用 cron。我使用 cron;我喜欢它,它很方便、熟悉等等。

但是 cron,在 10.5.8 Leopard 下(必需——驱动程序问题排除了 10.6),每次 启动时都会吐出主题消息,基本上会乱扔什么有用的窗户和无用的垃圾。在 crontab 中,我设置 PATH、SHELL 和 HOME 变量;用 python 编写的应用程序都可以正常运行,并且可以对所需的设备、目录和文件进行预期的读/写访问;他们可以正常启动其他 python 子任务;然而,在启动时就有 cron 的抱怨,好像出了什么问题。

也许有什么。但是谷歌搜索,我基本上发现了四件事:

1)这个问题已经存在了很长一段时间了——苹果还没有解决它

2)如果典型的cron启动实际上出了问题,似乎没有人知道它是什么

3)这是非常常见,通常的建议是“launchd”,这是行不通的

4) 唯一接近解决方案的建议是将控制台的 /etc/syslog.conf 日志记录级别设置为 err而不是通知;但在这种情况下,人们会失去控制台的许多好处,而且我非常不愿意以这种方式运行。

我希望在 stackoverflow 上,有人真正知道错误消息的具体含义(而不是“launchd 不高兴/崩溃”),或者甚至自己悄悄地解决了问题。

此外,如果我弄清楚了这一点——我已经在这上面花费了不合理的时间——我将在这里发布,以便其他人最终可以找到解决方案。

I have a data gathering app (terrestrial magnetic field strength) that has four phases; they run, via cron, at 2,3,4, and 5 minute intervals, ordered so that everything needed for one step is collected before it happens.

Because of the intervals, I can't, as I understand it, use launchd to fire the phases; consequently, I use cron. And I want to use cron; I like it, it's convenient, familiar, etc.

But cron, under 10.5.8 Leopard (required -- driver issues preclude 10.6), vomits the subject message with every launch, basically littering what would be a useful window with useless trash. In the crontab, I'm setting the PATH, SHELL and HOME variables; the apps, which are written in python, all run properly and with the expected R/W access to the equipment, directories and files they need to get at; they launch other python subtasks fine; yet, there's the complaint from cron at launch, as if something is wrong.

Perhaps something is. But googling, I basically found four things:

1) This problem has existed for a loooong time -- Apple has not addressed it

2) If something's actually wrong with a typical cron launch, no one seems to know what it is

3) This is really common, and the usual suggestion is "launchd", which won't work

4) The only suggestion even close to a solution is to set /etc/syslog.conf logging level for the console to err instead of notice; but then one loses many benefits of the console in that case, and I'm very reluctant to run that way.

What I"m hoping is that here on stackoverflow, there will be someone who actually knows specifically what the error message means (as opposed to "launchd is unhappy / busted") or has even quietly solved the problem on their own.

Also, if I figure this out -- I've spent an unconscionable number of hours on it already -- I'll post here and so others can finally find a solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冧九 2024-11-10 19:36:48

好的。我已经做了很多谷歌搜索,关于这个问题有几件事值得注意。首先,这个问题已经存在多年了。网络上对此有大量的投诉。我在苹果开发者论坛上发现了一篇帖子,据说苹果知道这一点,这是一个错误,并将在未来的某个时候修复。当然,这个评论是几年前发布的(实际上是三年前),而且显然,苹果不会修复它。与此同时,我收到了这些该死的控制台消息,这给我带来了严重的不便。我有真正的工作要做,我需要在该工作中使用控制台输出。

所以我修好了它。 :) 是的,我的 cron 作业现在正在安静且正确地运行,就像它们一直应该的那样。

现在,我想强调这是一个残酷的修复和黑客攻击,但它是针对问题的相当具体的,我认为它不会伤害任何其他东西(如果执行正确),并且完美地满足我的需求。您的里程可能会有所不同,如果您不是技术人员,请立即停止阅读并忘记您曾经看过这篇文章。真的。现在停下来。

基本上,正如您在上面发布的 Graham 从 launchd 中挖掘出的相关源代码块中看到的那样,有一个函数调用报告了这个特定的错误。几乎就是这个特定的错误。

它有四个参数,其中之一是通过调用 mach_error_string() 返回的。唯一作为指针的参数(意味着被调用的例程可以以某种方式返回到原始参数)是字符串指针,以及静态格式字符串的自修改......不。这不是认真喝 Koolaid 的人会做的事情。所以调用不会对这些参数做任何事情;它只是使用它们来报告错误。很明显,我们不需要拨打这个电话。啊哈。 :)

对 mach_error_string 的调用是 10.5.8 版本的 launchd 中的唯一签名。这使我能够精确定位 launchd 可执行文件中的代码。一旦到了那里,发生的事情就很明显了(至少对我来说);有适当数量的移动指令,然后是调用,然后检查循环并退出或重新运行。以下是反汇编的相关部分:

+193    0000fcd9  e87e050100              calll       0x0002025c                    _mach_error_string
+198    0000fcde  89442410                movl        %eax,0x10(%esp)
+202    0000fce2  8b462c                  movl        0x2c(%esi),%eax
+205    0000fce5  c7442408b8b90100        movl        $0x0001b9b8,0x08(%esp)
+213    0000fced  895c2404                movl        %ebx,0x04(%esp)
+217    0000fcf1  893c24                  movl        %edi,(%esp)
+220    0000fcf4  c1e808                  shrl        $0x08,%eax
+223    0000fcf7  25ff030000              andl        $0x000003ff,%eax
+228    0000fcfc  8944240c                movl        %eax,0x0c(%esp)
+232    0000fd00  e857afffff              calll       0x0000ac5c

调用的二进制签名(我再次强调,在我机器上的 launchd 10.5.8 版本中)是:E857AFFFFF。整个文件中只有一个该二进制字符串的实例。

我们在这里需要做的是将其替换为相同长度的无害(在上下文中)的内容。附近有一个 eax 的立即 AND 指令;就可以了。由于循环在调用后结束,因此 eax 中的值不会再次使用。该 AND 指令的二进制为:25FF030000。即使在最坏的情况下,在加载时,代码被重新链接以便调用地址发生改变,所发生的只是 and 指令将具有不同的 AND 模式。所以无论如何,这样做应该没问题。

因此,我们用 25FF030000 替换 E857AFFFFF,现在代码所做的就是加载这些参数,并且 eax 寄存器完全没有意义,然后继续生活。不再出现“无法设置 Mach 任务特殊端口 %u: %s”消息。曾经。 launchd 将继续像往常一样工作,因为这里所做的只是删除记录错误消息的调用。

现在...只是几句结束语。

首先,虽然黑客攻击非常具体,但它并不是我所说的精确到外科手术。可能潜伏在某处的情况会合法地调用此消息,或者使用此格式字符串和末尾带有不同端口号和/或字符串的参数发出的消息;如果发生这种情况,则不会被记录。所以要注意这一点。错误处理不会改变,但日志记录......现在这是不可能的。

其次,这是经典意义上的黑客攻击;对我来说,这既有趣又令人满意,它的目的是让我在苹果公司的总体方向上提高我的中心数字,因为他们可以轻松地自行修复一些问题,给我带来不便;不过,对于您来说,如果您对机器代码和二进制文件不满意,和/或不太确定您是否可以完全正确地执行此操作...并且您还没有完全准备好必须火线连接到您的机器并替换被黑客攻击的代码再次使用原始版本启动...或者您没有 10.5.8...甚至不要尝试它。只需写信给 Apple 并告诉他们修复损坏的 launchd 即可。

所以...苹果给了我们一个错误;固定球时掉落;我完全失去了耐心,把它从脸上抹掉了。现在你就得到了它。噗噗。

Ok. I've done a LOT of googling, and there are several things of note about this issue. First, the problem has existed for years. There are huge numbers of complaints about it on the net. I found a post in the Apple dev forums where it was said that Apple knew about it, it's a bug, and would be fixed at some future point. Of course, that remark was posted years ago (three, in fact), and apparently, Apple isn't going to fix it. And in the meantime, I have these bloody console messages which are seriously inconveniencing me. I have real work to do and I need to use the console output in that work.

So I fixed it. :) Yes, my cron jobs are now running quietly and correctly, the way they always should have.

Now, I would like to emphasize that this is a brutal fix, and a hack, but it is fairly specific to the problem, I don't think it can hurt anything else (if performed correctly), and serves MY needs perfectly. Your mileage may differ, and if you're not a technical person, stop reading now and just forget your ever saw this post. Really. Stop now.

So basically, as you can see in the above posting of the relevant chunk of source code from launchd that Graham dug up, there's a function call that reports this particular error. And pretty much just this particular error.

It has four parameters, one of which is returned from a call to mach_error_string(). The only parameter that is a pointer (meaning, the called routine could somehow get back to the original parameter) is the string pointer, and self-modification of a static format string... nah. That's not the kind of thing serious Koolaid drinkers would ever do. So the call isn't doing anything to those parameters; its just using them to report the error. So clearly, we don't need to make this call. Ah-ha. :)

This call to mach_error_string turns out to be a unique signature in the 10.5.8 version of launchd. That allowed me to precisely locate the code within the launchd executable. Once there, it was pretty obvious (to me, anyway) what is going on; there are the appropriate number of move instructions, then the call, then the loop is checked and either exited or re-run. Here's the relevant portion of the disassembly:

+193    0000fcd9  e87e050100              calll       0x0002025c                    _mach_error_string
+198    0000fcde  89442410                movl        %eax,0x10(%esp)
+202    0000fce2  8b462c                  movl        0x2c(%esi),%eax
+205    0000fce5  c7442408b8b90100        movl        $0x0001b9b8,0x08(%esp)
+213    0000fced  895c2404                movl        %ebx,0x04(%esp)
+217    0000fcf1  893c24                  movl        %edi,(%esp)
+220    0000fcf4  c1e808                  shrl        $0x08,%eax
+223    0000fcf7  25ff030000              andl        $0x000003ff,%eax
+228    0000fcfc  8944240c                movl        %eax,0x0c(%esp)
+232    0000fd00  e857afffff              calll       0x0000ac5c

The binary signature of the call (again, I emphasize, in the 10.5.8 version of launchd on my machine) is: E857AFFFFF. There's only one instance of this binary string in the entire file.

What we need to do here is replace that with something harmless (in context) of the same length. nearby, there's an immediate AND instruction for eax; that'll do. The value in eax isn't used again as the loop ends after the call. The binary for that AND instruction is: 25FF030000. Even if, worst case, at load time, the code were relinked so that (what was) the calll address was changed, all that would happen is the and instruction would have a different AND pattern. So no matter what, this should be ok to do.

So we replace the E857AFFFFF with 25FF030000, and now what the code does is load up those parameters, AND the eax register to no point at all, and go on with life. no more "Could not setup Mach task special port %u: %s" messages. Ever. And launchd will continue to work just like it always did, because all that has been done here is to excise a call to log an error message.

Now... just a couple closing remarks.

First, although the hack is quite specific, it isn't what I'd call surgically precise; it is possible that there might be lurking somewhere a situation that would legitimately call for this message, or a message emitted using this format string and parameters with a different port number and/or string at the end; and that's not going to be logged if it happens. So be aware of that. Error handling, such as it is, won't change, but the logging... that's now impossible.

Second, this is hacking in the classic sense; for me, it was both fun and very satisfying, serving the purpose of raising my central digit in Apple's general direction for inconveniencing me with something they could have easily fixed themselves; for you, though, if you're not comfortable with machine code and binary, and/or not very certain you can do this exactly right... and you're not completely prepared to have to firewire into your machine and replace the hacked launchd with the original again... or you don't have 10.5.8... don't even try it. Just write Apple and tell 'em to fix their broken launchd.

So... Apple gives us a bug; drops the ball on fixing it; I entirely lost patience and hacked it out of my face. And there you have it. Pbbffft.

江湖彼岸 2024-11-10 19:36:48

让我们看看来源:)。在 http://www.opensource.apple.com/ 中搜索错误消息会在 < a href="http://www.opensource.apple.com/source/launchd/launchd-258.18/launchd/src/launchd_core_logic.c" rel="nofollow">launchd_core_logic.c:

kern_return_t
job_mig_post_fork_ping(job_t j, task_t child_task)
{
    struct machservice *ms;

    if (!launchd_assumes(j != NULL)) {
        return BOOTSTRAP_NO_MEMORY;
    }

    job_log(j, LOG_DEBUG, "Post fork ping.");

    job_setup_exception_port(j, child_task);

    SLIST_FOREACH(ms, &special_ports, special_port_sle) {
        if (j->per_user && (ms->special_port_num != TASK_ACCESS_PORT)) {
            /* The TASK_ACCESS_PORT funny business is to workaround 5325399. */
            continue;
        }

        errno = task_set_special_port(child_task, ms->special_port_num, ms->port);

        if (errno) {
            int desired_log_level = LOG_ERR;

            if (j->anonymous) {
                /* 5338127 */

                desired_log_level = LOG_WARNING;

                if (ms->special_port_num == TASK_SEATBELT_PORT) {
                    desired_log_level = LOG_DEBUG;
                }
            }

            job_log(j, desired_log_level, "Could not setup Mach task special port %u: %s", ms->special_port_num, mach_error_string(errno));
        }
    }

    job_assumes(j, launchd_mport_deallocate(child_task) == KERN_SUCCESS);

    return 0;
}

好的,所以从在这里,您应该能够找到特殊端口号 9 的名称,以及 launchd 在发布消息时试图执行的操作。看起来像是在将 mach 端口从 launchd 转移到子进程的过程中,但我不知道它在那里做什么。您可能需要发送电子邮件至 [email protected]并询问他们雷达 5325399 和 5338127 是什么,因为这些雷达似乎与该功能的实现相关。

Let's look at the source :). Searching for your error message in http://www.opensource.apple.com/ finds this in launchd_core_logic.c:

kern_return_t
job_mig_post_fork_ping(job_t j, task_t child_task)
{
    struct machservice *ms;

    if (!launchd_assumes(j != NULL)) {
        return BOOTSTRAP_NO_MEMORY;
    }

    job_log(j, LOG_DEBUG, "Post fork ping.");

    job_setup_exception_port(j, child_task);

    SLIST_FOREACH(ms, &special_ports, special_port_sle) {
        if (j->per_user && (ms->special_port_num != TASK_ACCESS_PORT)) {
            /* The TASK_ACCESS_PORT funny business is to workaround 5325399. */
            continue;
        }

        errno = task_set_special_port(child_task, ms->special_port_num, ms->port);

        if (errno) {
            int desired_log_level = LOG_ERR;

            if (j->anonymous) {
                /* 5338127 */

                desired_log_level = LOG_WARNING;

                if (ms->special_port_num == TASK_SEATBELT_PORT) {
                    desired_log_level = LOG_DEBUG;
                }
            }

            job_log(j, desired_log_level, "Could not setup Mach task special port %u: %s", ms->special_port_num, mach_error_string(errno));
        }
    }

    job_assumes(j, launchd_mport_deallocate(child_task) == KERN_SUCCESS);

    return 0;
}

OK, so from here you should be able to find the name of the special port number 9, and therefore what launchd is trying to do when it posts the message. It looks like it's during the business of transferring mach ports from launchd to the child process, but I don't know what it's doing there. You may want to email [email protected] and ask them what radars 5325399 and 5338127 are, as these seem relevant to the implementation of that function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文