mirror of
https://github.com/FeralInteractive/gamemode.git
synced 2025-06-06 23:57:22 +02:00
daemon: add ref-counting to GameModeClient
This is so it can out-live its membership in the client list, e.g. when it is passed outside of gamemode-context.c and the reaper comes along and reaps a client in the background but we still are using the struct outside.
This commit is contained in:
parent
2027e981e6
commit
1a863f32a1
@ -52,6 +52,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
* form to contain the pid and credentials.
|
* form to contain the pid and credentials.
|
||||||
*/
|
*/
|
||||||
struct GameModeClient {
|
struct GameModeClient {
|
||||||
|
_Atomic int refcount; /**<Allow outside usage */
|
||||||
pid_t pid; /**< Process ID */
|
pid_t pid; /**< Process ID */
|
||||||
struct GameModeClient *next; /**<Next client in the list */
|
struct GameModeClient *next; /**<Next client in the list */
|
||||||
char executable[PATH_MAX]; /**<Process executable */
|
char executable[PATH_MAX]; /**<Process executable */
|
||||||
@ -86,7 +87,7 @@ static GameModeContext instance = { 0 };
|
|||||||
static volatile bool had_context_init = false;
|
static volatile bool had_context_init = false;
|
||||||
|
|
||||||
static GameModeClient *game_mode_client_new(pid_t pid, char *exe);
|
static GameModeClient *game_mode_client_new(pid_t pid, char *exe);
|
||||||
static void game_mode_client_free(GameModeClient *client);
|
static void game_mode_client_unref(GameModeClient *client);
|
||||||
static const GameModeClient *game_mode_context_has_client(GameModeContext *self, pid_t client);
|
static const GameModeClient *game_mode_context_has_client(GameModeContext *self, pid_t client);
|
||||||
static void *game_mode_context_reaper(void *userdata);
|
static void *game_mode_context_reaper(void *userdata);
|
||||||
static void game_mode_context_enter(GameModeContext *self);
|
static void game_mode_context_enter(GameModeContext *self);
|
||||||
@ -159,7 +160,7 @@ void game_mode_context_destroy(GameModeContext *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
had_context_init = false;
|
had_context_init = false;
|
||||||
game_mode_client_free(self->client);
|
game_mode_client_unref(self->client);
|
||||||
|
|
||||||
end_reaper_thread(self);
|
end_reaper_thread(self);
|
||||||
|
|
||||||
@ -444,7 +445,7 @@ error_cleanup:
|
|||||||
if (errno != 0)
|
if (errno != 0)
|
||||||
LOG_ERROR("Failed to register client [%d]: %s\n", client, strerror(errno));
|
LOG_ERROR("Failed to register client [%d]: %s\n", client, strerror(errno));
|
||||||
free(executable);
|
free(executable);
|
||||||
game_mode_client_free(cl);
|
game_mode_client_unref(cl);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,7 +509,7 @@ int game_mode_context_unregister(GameModeContext *self, pid_t client, pid_t requ
|
|||||||
self->client = cl->next;
|
self->client = cl->next;
|
||||||
}
|
}
|
||||||
cl->next = NULL;
|
cl->next = NULL;
|
||||||
game_mode_client_free(cl);
|
game_mode_client_unref(cl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -616,20 +617,24 @@ static GameModeClient *game_mode_client_new(pid_t pid, char *executable)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*ret = c;
|
*ret = c;
|
||||||
|
ret->refcount = ATOMIC_VAR_INIT(1);
|
||||||
strncpy(ret->executable, executable, PATH_MAX - 1);
|
strncpy(ret->executable, executable, PATH_MAX - 1);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free a client and the next element in the list.
|
* Unref a client and the next element in the list, if non-null.
|
||||||
*/
|
*/
|
||||||
static void game_mode_client_free(GameModeClient *client)
|
static void game_mode_client_unref(GameModeClient *client)
|
||||||
{
|
{
|
||||||
if (!client) {
|
if (!client) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (atomic_fetch_sub_explicit(&client->refcount, 1, memory_order_seq_cst) > 1) {
|
||||||
|
return; /* object is still alive */
|
||||||
|
}
|
||||||
if (client->next) {
|
if (client->next) {
|
||||||
game_mode_client_free(client->next);
|
game_mode_client_unref(client->next);
|
||||||
}
|
}
|
||||||
free(client);
|
free(client);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user