net_server: Replace fork+exec with posix_spawn.
Uses POSIX_SPAWN_SETSID, so needs the previous commit to work.
This commit is contained in:
@@ -13,12 +13,14 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <spawn.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#include <Autolock.h>
|
#include <Autolock.h>
|
||||||
|
#include <AutoDeleter.h>
|
||||||
#include <NetworkAddress.h>
|
#include <NetworkAddress.h>
|
||||||
#include <NetworkSettings.h>
|
#include <NetworkSettings.h>
|
||||||
|
|
||||||
@@ -426,51 +428,56 @@ Services::_LaunchService(struct service& service, int socket)
|
|||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t child = fork();
|
posix_spawnattr_t attr;
|
||||||
if (child == 0) {
|
status_t status = posix_spawnattr_init(&attr);
|
||||||
setsid();
|
if (status != 0)
|
||||||
// make sure we're in our own session, and don't accidently quit
|
return status;
|
||||||
// the net_server
|
CObjectDeleter<posix_spawnattr_t, int, posix_spawnattr_destroy>
|
||||||
|
attrDeleter(&attr);
|
||||||
|
|
||||||
if (socket != -1) {
|
posix_spawn_file_actions_t fileActions;
|
||||||
// We're the child, replace standard input/output
|
status = posix_spawn_file_actions_init(&fileActions);
|
||||||
dup2(socket, STDIN_FILENO);
|
if (status != 0)
|
||||||
dup2(socket, STDOUT_FILENO);
|
return status;
|
||||||
dup2(socket, STDERR_FILENO);
|
CObjectDeleter<posix_spawn_file_actions_t, int, posix_spawn_file_actions_destroy>
|
||||||
close(socket);
|
actionsDeleter(&fileActions);
|
||||||
}
|
|
||||||
|
|
||||||
// build argument array
|
// make sure the child has its own session, and doesn't accidentally quit
|
||||||
|
// the net_server
|
||||||
|
posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSID);
|
||||||
|
|
||||||
const char** args = (const char**)malloc(
|
// replace standard input/output in the child
|
||||||
(service.arguments.size() + 1) * sizeof(char*));
|
posix_spawn_file_actions_adddup2(&fileActions, socket, STDIN_FILENO);
|
||||||
if (args == NULL)
|
posix_spawn_file_actions_adddup2(&fileActions, socket, STDOUT_FILENO);
|
||||||
exit(1);
|
posix_spawn_file_actions_adddup2(&fileActions, socket, STDERR_FILENO);
|
||||||
|
posix_spawn_file_actions_addclose(&fileActions, socket);
|
||||||
|
|
||||||
for (size_t i = 0; i < service.arguments.size(); i++) {
|
// build argument array
|
||||||
args[i] = service.arguments[i].c_str();
|
const char** args = (const char**)malloc(
|
||||||
}
|
(service.arguments.size() + 1) * sizeof(char*));
|
||||||
args[service.arguments.size()] = NULL;
|
if (args == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
MemoryDeleter argsDeleter(args);
|
||||||
|
|
||||||
if (execv(service.arguments[0].c_str(), (char* const*)args) < 0) {
|
for (size_t i = 0; i < service.arguments.size(); i++)
|
||||||
free(args);
|
args[i] = service.arguments[i].c_str();
|
||||||
exit(1);
|
args[service.arguments.size()] = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
// we'll never trespass here
|
// spawn
|
||||||
} else {
|
pid_t child;
|
||||||
// the server does not need the socket anymore
|
status = posix_spawn(&child, service.arguments[0].c_str(),
|
||||||
if (socket != -1)
|
&fileActions, &attr, (char* const*)args, NULL);
|
||||||
close(socket);
|
|
||||||
|
|
||||||
if (child < 0) {
|
if (status != 0 || child < 0) {
|
||||||
fprintf(stderr, "Could not start service %s\n",
|
fprintf(stderr, "Could not start service %s\n",
|
||||||
service.name.c_str());
|
service.name.c_str());
|
||||||
} else if (service.stand_alone)
|
} else if (service.stand_alone)
|
||||||
service.process = child;
|
service.process = child;
|
||||||
}
|
|
||||||
|
// the server does not need the socket anymore
|
||||||
|
if (socket != -1)
|
||||||
|
close(socket);
|
||||||
|
|
||||||
// TODO: make sure child started successfully...
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user