我正在使用 AuthorizationExecuteWithPriveleges 以管理员权限从我的应用程序执行 bash 命令。我发现了非常奇怪的问题。这是我正在使用的
FILE *pipe=nil;
OSStatus err;
AuthorizationRef authorizationRef;
char *command= "/bin/chmod";
char *args[] = {"644","folderPath", nil};
if(err!=0)
{
err = AuthorizationCreate(nil,
kAuthorizationEmptyEnvironment,
kAuthorizationFlagDefaults,
&authorizationRef);
}
NSLog(@"test");
err = AuthorizationExecuteWithPrivileges(authorizationRef,
command,
kAuthorizationFlagDefaults,
args,
&pipe);
调用此函数大约 40 次后,开始响应非常缓慢。之后它就会死掉,并卡住应用程序,我不知道这是怎么回事。在调用大约 40 次后,它没有显示日志“测试”,也没有做任何事情。 使用什么 Bash 命令或什么参数并不重要。它仍然做同样的事情。这有什么问题?我之所以使用它,是因为我的应用程序也需要在 10.5 上运行。
如果有人有想法,我该怎么办。对此,我真的非常感激。我需要尽快。谢谢
最佳答案
仔细研究了这一点,并编写了以下示例,没有任何保证,但对我来说,它可以毫无问题地调用数千次 AuthorizationExecuteWithPrivileges:
void DoOtherStuff(AuthorizationRef auth, char* path);
void DoStuff(char* path)
{
AuthorizationItem foo;
foo.name = kAuthorizationRightExecute;
foo.value = NULL;
foo.valueLength = 0;
foo.flags = 0;
AuthorizationRights rights;
rights.count = 1;
rights.items = &foo;
AuthorizationRef authorizationRef;
OSStatus err = errAuthorizationSuccess;
if (errAuthorizationSuccess != (err = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef)))
{
NSLog(@"Error on AuthorizationCreate: %lu", (long)err);
return;
}
for (NSUInteger i = 0; i < 5000; i++)
{
NSLog(@"Doing run: %lu", (long)i+1);
DoOtherStuff(authorizationRef, "/tmp/foo");
}
if (errAuthorizationSuccess != (err = AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults)))
{
NSLog(@"Error on AuthorizationFree: %lu", (long)err);
return;
}
}
void DoOtherStuff(AuthorizationRef authorizationRef, char* path)
{
OSStatus err = errAuthorizationSuccess;
FILE *pipe = NULL;
@try
{
char *args[] = {"644", path, NULL};
if (errAuthorizationSuccess != (err = AuthorizationExecuteWithPrivileges(authorizationRef,
"/bin/chmod", kAuthorizationFlagDefaults, args, &pipe)))
{
NSLog(@"Error on AuthorizationExecuteWithPrivileges: %lu", (long)err);
return;
}
int stat;
wait(&stat);
NSLog(@"Success! Child Process Died!");
}
@finally
{
if (pipe)
fclose(pipe);
}
}
Chris Suter 所说的完全正确。当您调用 AuthorizationExecuteWithPrivileges 时发生的事情是它 fork()s 您的进程,然后 exec()s 从子进程请求的进程(在本例中为 chmod)。在有人调用 wait() 之前,子进程不会被收割,但这很难,因为我们无法从 AuthorizationExecuteWithPrivileges 中获取子进程的 PID(它会由 fork() 返回)。正如他所说,如果您确定没有其他线程同时产生进程(即您的线程是唯一创建子进程的线程),那么您可以调用 wait() 的非 PID 特定版本,例如我在这个例子中这样做。
如果您不调用 wait() ,那么您会累积这些等待收割的僵尸子进程。最终操作系统说“不再”。
我觉得发布这个有点不好,因为它只是对 Chris Suter 所说内容的翻版;我赞成他的回答。
为了完整起见,这里是该示例的修改版本,它通过忽略 SIGCHLD 而不是调用等待来实现目标。它也没有保修,但对我有用。
void DoOtherStuff(AuthorizationRef auth, char* path);
void DoStuff(char* path)
{
AuthorizationItem foo;
foo.name = kAuthorizationRightExecute;
foo.value = NULL;
foo.valueLength = 0;
foo.flags = 0;
AuthorizationRights rights;
rights.count = 1;
rights.items = &foo;
AuthorizationRef authorizationRef;
OSStatus err = errAuthorizationSuccess;
struct sigaction oldAction;
struct sigaction newAction;
newAction.__sigaction_u.__sa_handler = SIG_IGN;
newAction.sa_mask = 0;
newAction.sa_flags = 0;
if(0 != sigaction(SIGCHLD, &newAction, &oldAction))
{
NSLog(@"Couldn't ignore SIGCHLD");
return;
}
@try
{
if (errAuthorizationSuccess != (err = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef)))
{
NSLog(@"Error on AuthorizationCreate: %lu", (long)err);
return;
}
for (NSUInteger i = 0; i < 1000; i++)
{
NSLog(@"Doing run: %lu", (long)i+1);
DoOtherStuff(authorizationRef, "/tmp/foo");
}
if (errAuthorizationSuccess != (err = AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults)))
{
NSLog(@"Error on AuthorizationFree: %lu", (long)err);
return;
}
}
@finally
{
const struct sigaction cOldAction = oldAction;
if(0 != sigaction(SIGCHLD, &cOldAction, NULL))
{
NSLog(@"Couldn't restore the handler for SIGCHLD");
return;
}
}
}
void DoOtherStuff(AuthorizationRef authorizationRef, char* path)
{
OSStatus err = errAuthorizationSuccess;
FILE *pipe = NULL;
@try
{
char *args[] = {"644", path, NULL};
if (errAuthorizationSuccess != (err = AuthorizationExecuteWithPrivileges(authorizationRef,
"/bin/chmod", kAuthorizationFlagDefaults, args, &pipe)))
{
NSLog(@"Error on AuthorizationExecuteWithPrivileges: %lu", (long)err);
return;
}
NSLog(@"Success!");
}
@finally
{
if (pipe)
fclose(pipe);
}
}
关于objective-c - Cocoa 中 AuthorizationExecuteWithPriveleges 的非常奇怪的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8094683/