bsnes/nall/posix/service.hpp
Tim Allen 0b923489dd Update to 20160106 OS X Preview for Developers release.
byuu says:

New update. Most of the work today went into eliminating hiro::Image
from all objects in all ports, replacing with nall::image. That took an
eternity.

Changelog:
- fixed crashing bug when loading games [thanks endrift!!]
- toggling "show status bar" option adjusts window geometry (not
  supposed to recenter the window, though)
- button sizes improved; icon-only button icons no longer being cut off
2016-01-07 19:17:15 +11:00

115 lines
2.7 KiB
C++

#pragma once
#include <signal.h>
namespace nall {
struct service {
inline explicit operator bool() const;
inline auto command(const string& name, const string& command) -> bool;
inline auto receive() -> string;
inline auto name() const -> string;
inline auto stop() const -> bool;
private:
shared_memory shared;
string _name;
bool _stop = false;
};
service::operator bool() const {
return (bool)shared;
}
//returns true on new service process creation (false is not necessarily an error)
auto service::command(const string& name, const string& command) -> bool {
if(!name) return false;
if(!command) return print("[{0}] usage: {service} command\n"
"commands:\n"
" status : query whether service is running\n"
" start : start service if it is not running\n"
" stop : stop service if it is running\n"
" remove : remove semaphore lock if service crashed\n"
" {value} : send custom command to service\n"
"", format{name}), false;
if(shared.open(name, 4096)) {
if(command == "start") {
print("[{0}] already started\n", format{name});
} else if(command == "status") {
print("[{0}] running\n", format{name});
}
if(auto data = shared.acquire()) {
if(command == "stop") print("[{0}] stopped\n", format{name});
memory::copy(data, command.data(), min(command.size(), 4096));
shared.release();
}
if(command == "remove") {
shared.remove();
print("[{0}] removed\n", format{name});
}
return false;
}
if(command == "start") {
if(shared.create(name, 4096)) {
print("[{0}] started\n", format{name});
auto pid = fork();
if(pid == 0) {
signal(SIGHUP, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
_name = name;
return true;
}
shared.close();
} else {
print("[{0}] start failed ({1})\n", format{name, strerror(errno)});
}
return false;
}
if(command == "status") {
print("[{0}] stopped\n", format{name});
return false;
}
return false;
}
auto service::receive() -> string {
string command;
if(shared) {
if(auto data = shared.acquire()) {
if(*data) {
command.resize(4095);
memory::copy(command.get(), data, 4095);
memory::fill(data, 4096);
}
shared.release();
if(command == "remove") {
_stop = true;
return "";
} else if(command == "start") {
return "";
} else if(command == "status") {
return "";
} else if(command == "stop") {
_stop = true;
shared.remove();
return "";
}
}
}
return command;
}
auto service::name() const -> string {
return _name;
}
auto service::stop() const -> bool {
return _stop;
}
}