* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef APPSPAWN_FD_MANAGER_H
#define APPSPAWN_FD_MANAGER_H
* @file appspawn_fd_manager.h
* @brief Spawning FD management module.
*
* Manages file descriptors created during the app spawning process,
* including prefork pipes and parent-child communication pipes.
* FDs are tracked in a per-pid linked list (spawningFdsQueue in AppSpawnMgr)
* to ensure proper lifecycle management and cleanup on process death.
*/
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include "list.h"
#ifdef __cplusplus
extern "C" {
#endif
* Forward declaration to avoid circular dependency with appspawn_manager.h.
* Full definition of TagAppSpawnMgr is in appspawn_manager.h.
*/
typedef struct TagAppSpawnMgr AppSpawnMgr;
* @brief Spawning FD type classification.
*/
typedef enum {
TYPE_FOR_DEC,
TYPE_FOR_FORK_ALL,
TYPE_CHILD_PARENT,
TYPE_PARENT_CHILD,
TYPE_INVALID
} SpawningFdType;
#define MAX_SPAWNING_FDS_PER_NODE 8
* @brief Save the fd information during the incubation process
* @param node Linked list head node
* @param type Fd type
* @param count Number of current Fd types
* @param fd File handle set
* @param pid Process ID (0 for global fd)
* @param timestamp Creation timestamp
*/
typedef struct {
struct ListNode node;
SpawningFdType type;
uint32_t count;
pid_t pid;
uint64_t timestamp;
int fds[0];
} AppSpawnFds;
* @brief Key type for spawning fd lookup by pid and type.
* Used as search criteria in OH_ListFind with SpawningFdPidComparePro.
*/
typedef struct {
pid_t pid;
SpawningFdType type;
} SpawningFdKey;
* @brief Registration info for spawning fd.
* Input parameter for RegisterSpawningFds(). Caller provides fd array
* which will be copied into the newly allocated AppSpawnFds node.
*/
typedef struct {
SpawningFdType type;
uint32_t count;
const int *fds;
pid_t pid;
} SpawningFdRegInfo;
* @brief Register spawning FDs to the management queue.
*
* Allocates a new AppSpawnFds node, copies the provided FDs, and appends
* it to mgr->spawningFdsQueue. Can be used before or after fork() to track
* pipe FDs associated with a specific child process.
*
* @param mgr AppSpawn manager instance (must not be NULL)
* @param regInfo Registration info containing FDs to track
* @return Pointer to the newly created AppSpawnFds node on success, NULL on failure
*/
AppSpawnFds *RegisterSpawningFds(AppSpawnMgr *mgr, const SpawningFdRegInfo *regInfo);
* @brief Find spawning FD node by pid and type.
*
* Searches mgr->spawningFdsQueue for a node matching the given pid and type.
* The returned pointer remains owned by the queue; do not free it.
*
* @param mgr AppSpawn manager instance
* @param pid Process ID to match
* @param type FD type to match
* @return Pointer to found node, or NULL if not found
*/
AppSpawnFds *FindSpawningFdsByPid(const AppSpawnMgr *mgr, pid_t pid, SpawningFdType type);
* @brief Unregister and close spawning FDs.
*
* Removes the node from the queue, closes all FDs it holds, and frees memory.
* Use when FDs are no longer needed (e.g., pipe write completed).
*
* @param mgr AppSpawn manager instance
* @param pid Process ID to match
* @param type FD type to match
* @return 0 on success, APPSPAWN_ARG_INVALID if not found
*/
int UnregisterSpawningFdsByPid(AppSpawnMgr *mgr, pid_t pid, SpawningFdType type);
* @brief Remove spawning FD node without closing FDs (ownership transfer).
*
* Removes the node from the queue and frees memory, but does NOT close
* the FDs. Use when FD ownership is being transferred to another context
* (e.g., from spawningFdsQueue to forkCtx).
*
* @param mgr AppSpawn manager instance
* @param pid Process ID to match
* @param type FD type to match
* @return 0 on success, APPSPAWN_ARG_INVALID if not found
*/
int RemoveSpawningFdsByPid(AppSpawnMgr *mgr, pid_t pid, SpawningFdType type);
* @brief Delete spawning FD node by pointer without closing FDs.
*
* Removes the node from the queue and frees memory, but does NOT close FDs.
* Sets the caller's pointer to NULL to prevent dangling pointer access.
* Use when FD ownership is being transferred or node was registered with
* a placeholder pid that needs to be cleaned up.
*
* @param fds Pointer to the AppSpawnFds node pointer (obtained from RegisterSpawningFds)
*/
void DeleteSpawningFds(AppSpawnFds **fds);
* @brief Cleanup all spawning FDs for a given pid.
*
* Iterates the queue, removes ALL nodes matching the pid (regardless of type),
* closes their FDs, and frees memory. Used when a child process dies or
* needs to be cleaned up.
*
* @param mgr AppSpawn manager instance
* @param pid Process ID to clean up
* @return Number of nodes cleaned up
*/
uint32_t CleanupSpawningFdsByPid(AppSpawnMgr *mgr, pid_t pid);
* @brief Dump spawning FD queue info for debug.
*
* Iterates the entire queue and logs type, pid, timestamp,
* and individual FD values via APPSPAWN_DUMP.
*
* @param mgr AppSpawn manager instance
*/
void DumpSpawningFds(const AppSpawnMgr *mgr);
* @brief Get spawning FD statistics.
*
* Counts total nodes, prefork nodes, and parent-child nodes in the queue.
*
* @param mgr AppSpawn manager instance
* @param total [out] Total number of nodes
* @param childParentCount [out] Number of TYPE_CHILD_PARENT nodes
* @param parentChildCount [out] Number of TYPE_PARENT_CHILD nodes
*/
void GetSpawningFdsStats(const AppSpawnMgr *mgr, uint32_t *total, uint32_t *childParentCount,
uint32_t *parentChildCount);
* @brief Destroy callback for spawning FD node.
*
* Closes all FDs held by the node and frees the node memory.
* Designed as a callback for list traversal cleanup.
*
* @param node ListNode embedded in AppSpawnFds
*/
void SpawningFdsDestroy(ListNode *node);
#ifdef __cplusplus
}
#endif
#endif