libamxp  1.4.0
Patterns C Implementation
amxp_subproc.c File Reference
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <poll.h>
#include <time.h>
#include <amxc/amxc_macros.h>
#include <amxc/amxc.h>
#include <amxp/amxp.h>

Go to the source code of this file.

Macros

#define _GNU_SOURCE
 
#define AMXP_SUB_PROC_NR_PIPES   3
 
#define AMXP_SUBPROC_FD_PARENT   0
 
#define AMXP_SUBPROC_FD_CHILD   1
 

Functions

static int amxp_subproc_child_status (amxp_subproc_t *subproc, int status)
 
static void amxp_subproc_close_fds (void)
 
static void amxp_subproc_exec_child (amxp_subproc_t *const subproc, char **argv)
 
static void amxp_subproc_sigchild (UNUSED const char *const sig_name, UNUSED const amxc_var_t *const data, UNUSED void *const priv)
 
static int amxp_recalculate_timeout (struct timespec *start, int timeout_msec)
 
int amxp_subproc_new (amxp_subproc_t **subproc)
 Constructor function, creates a new child process data structure. More...
 
int amxp_subproc_delete (amxp_subproc_t **subproc)
 Destructor function, deletes a child process data structure. More...
 
int amxp_subproc_open_fd (amxp_subproc_t *subproc, int requested)
 Opens standard file descriptor to the child process. More...
 
int amxp_subproc_vstart (amxp_subproc_t *const subproc, char **argv)
 Start a child process. More...
 
int amxp_subproc_start (amxp_subproc_t *const subproc, char *cmd,...)
 Start a child process. More...
 
int amxp_subproc_astart (amxp_subproc_t *const subproc, amxc_array_t *cmd)
 Start a child process. More...
 
int amxp_subproc_kill (const amxp_subproc_t *const subproc, const int sig)
 Sends a Linux signal to the child process. More...
 
amxp_subproc_tamxp_subproc_find (const int pid)
 Retrieve a amxp_subproc_t for a child process using it's process identifier. More...
 
pid_t amxp_subproc_get_pid (const amxp_subproc_t *const subproc)
 Get the PID of a child process. More...
 
amxp_signal_mngr_tamxp_subproc_get_sigmngr (const amxp_subproc_t *const subproc)
 Get the Signal managers of the child process. More...
 
bool amxp_subproc_is_running (const amxp_subproc_t *const subproc)
 Checks if the child process is running. More...
 
int amxp_subproc_wait (amxp_subproc_t *subproc, int timeout_msec)
 Waits until the child process has stopped. More...
 
int amxp_subproc_vstart_wait (amxp_subproc_t *subproc, int timeout_msec, char **cmd)
 Starts a child process and waits until it exits. More...
 
int amxp_subproc_start_wait (amxp_subproc_t *subproc, int timeout_msec, char *cmd,...)
 Starts a child process and waits until it exits. More...
 
int amxp_subproc_ifexited (amxp_subproc_t *subproc)
 Checks if the child process terminated normally. More...
 
int amxp_subproc_ifsignaled (amxp_subproc_t *subproc)
 Checks if the child process was stopped because of an uncaught Linux signal. More...
 
int amxp_subproc_get_exitstatus (amxp_subproc_t *subproc)
 Gets the exit code of the child process. More...
 
int amxp_subproc_get_termsig (amxp_subproc_t *subproc)
 Gets the Linux signal id that caused the child process to stop. More...
 

Variables

static amxc_llist_t amxp_subprocs
 

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE

Definition at line 56 of file amxp_subproc.c.

◆ AMXP_SUB_PROC_NR_PIPES

#define AMXP_SUB_PROC_NR_PIPES   3

Definition at line 74 of file amxp_subproc.c.

◆ AMXP_SUBPROC_FD_CHILD

#define AMXP_SUBPROC_FD_CHILD   1

Definition at line 77 of file amxp_subproc.c.

◆ AMXP_SUBPROC_FD_PARENT

#define AMXP_SUBPROC_FD_PARENT   0

Definition at line 76 of file amxp_subproc.c.

Function Documentation

◆ amxp_recalculate_timeout()

static int amxp_recalculate_timeout ( struct timespec *  start,
int  timeout_msec 
)
static

Definition at line 187 of file amxp_subproc.c.

187  {
188  int err;
189  struct timespec stop;
190  int remaining_timeout = 0;
191 
192  int msec_passed;
193  time_t sec_to_msec;
194  long nsec_to_msec;
195 
196  err = clock_gettime(CLOCK_REALTIME, &stop);
197  when_failed(err, exit);
198 
199  sec_to_msec = (( stop.tv_sec - start->tv_sec ) * ((time_t) 1000));
200  nsec_to_msec = (( stop.tv_nsec - start->tv_nsec) / ((long) 1000000));
201 
202  msec_passed = (int) sec_to_msec + (int) nsec_to_msec;
203  remaining_timeout = timeout_msec - msec_passed;
204 
205  if(remaining_timeout < 0) {
206  // this is to avoid that a timeout gets converted
207  // to wait indefinitely
208  remaining_timeout = 0;
209  }
210 
211 exit:
212  return remaining_timeout;
213 }

◆ amxp_subproc_child_status()

static int amxp_subproc_child_status ( amxp_subproc_t subproc,
int  status 
)
static

Definition at line 81 of file amxp_subproc.c.

81  {
82  int retval = -1;
83  amxc_var_t* exit_info = NULL;
84  amxc_var_t data;
85 
86  subproc->is_running = false;
87  subproc->status = status;
88 
89  amxc_var_init(&data);
90  amxc_var_new(&exit_info);
91  amxc_var_set_type(exit_info, AMXC_VAR_ID_HTABLE);
92 
93  amxc_var_set(int64_t, &data, subproc->pid);
94  amxc_var_set_key(exit_info, "PID", &data, AMXC_VAR_FLAG_COPY);
95 
96  if(WIFEXITED(status)) {
97  amxc_var_set(int64_t, &data, WEXITSTATUS(status));
98  amxc_var_set_key(exit_info, "ExitCode", &data, AMXC_VAR_FLAG_COPY);
99  } else if(WIFSIGNALED(status)) {
100  if(WCOREDUMP(status)) {
101  amxc_var_set(bool, &data, true);
102  amxc_var_set_key(exit_info, "CoreDump", &data, AMXC_VAR_FLAG_COPY);
103  } else {
104  amxc_var_set(bool, &data, true);
105  amxc_var_set_key(exit_info, "CoreDump", &data, AMXC_VAR_FLAG_COPY);
106  }
107  amxc_var_set(bool, &data, true);
108  amxc_var_set_key(exit_info, "Signalled", &data, AMXC_VAR_FLAG_COPY);
109  amxc_var_set(int64_t, &data, WTERMSIG(status));
110  amxc_var_set_key(exit_info, "Signal", &data, AMXC_VAR_FLAG_COPY);
111  } else {
112  goto exit;
113  }
114 
115 
116  amxp_sigmngr_emit_signal(subproc->sigmngr, "stop", exit_info);
117  amxc_var_delete(&exit_info);
118 
119  retval = 0;
120 
121 exit:
122  return retval;
123 }
int amxp_sigmngr_emit_signal(const amxp_signal_mngr_t *const sig_mngr, const char *name, const amxc_var_t *const data)
Emits a signal.
Definition: amxp_signal.c:514
amxp_signal_mngr_t * sigmngr
Definition: amxp_subproc.h:93
bool is_running
Definition: amxp_subproc.h:90

◆ amxp_subproc_close_fds()

static void amxp_subproc_close_fds ( void  )
static

Definition at line 125 of file amxp_subproc.c.

125  {
126  struct rlimit limit;
127  int max_files = 1024;
128 
129  int ret = getrlimit(RLIMIT_NOFILE, &limit);
130  if(ret == 0) {
131  max_files = limit.rlim_cur;
132  }
133 
134  for(int i = 3; i < max_files; i++) {
135  close(i);
136  }
137 }

◆ amxp_subproc_exec_child()

static void amxp_subproc_exec_child ( amxp_subproc_t *const  subproc,
char **  argv 
)
static

Definition at line 139 of file amxp_subproc.c.

140  {
141  int fd_null = -1;
142  sigset_t sig_set;
143 
144  prctl(PR_SET_PDEATHSIG, SIGKILL);
145 
146  fd_null = open("/dev/null", O_RDWR);
147  for(int i = 0; i < AMXP_SUB_PROC_NR_PIPES; i++) {
148  if(subproc->fd[i][AMXP_SUBPROC_FD_CHILD] >= 0) {
149  if(i != subproc->fd[i][AMXP_SUBPROC_FD_CHILD]) {
150  close(i);
151  dup2(subproc->fd[i][AMXP_SUBPROC_FD_CHILD], i);
152  }
153  } else {
154  dup2(fd_null, i);
155  }
156  }
157 
159 
160  pthread_sigmask(SIG_SETMASK, NULL, &sig_set);
161  pthread_sigmask(SIG_UNBLOCK, &sig_set, NULL);
162 
163  execvp(argv[0], argv);
164 
165  _exit(EXIT_FAILURE);
166 }
static void amxp_subproc_close_fds(void)
Definition: amxp_subproc.c:125
#define AMXP_SUBPROC_FD_CHILD
Definition: amxp_subproc.c:77
#define AMXP_SUB_PROC_NR_PIPES
Definition: amxp_subproc.c:74
int fd[3][2]
Definition: amxp_subproc.h:91

◆ amxp_subproc_sigchild()

static void amxp_subproc_sigchild ( UNUSED const char *const  sig_name,
UNUSED const amxc_var_t *const  data,
UNUSED void *const  priv 
)
static

Definition at line 168 of file amxp_subproc.c.

170  {
171  int status = -1;
172  pid_t ret = -1;
173  amxp_subproc_t* subproc;
174 
175  while((ret = waitpid(-1, &status, WNOHANG)) > 0) {
176  subproc = amxp_subproc_find(ret);
177  if(subproc == NULL) {
178  continue;
179  }
180 
181  amxp_subproc_child_status(subproc, status);
182  }
183 
184  return;
185 }
static int amxp_subproc_child_status(amxp_subproc_t *subproc, int status)
Definition: amxp_subproc.c:81
amxp_subproc_t * amxp_subproc_find(const int pid)
Retrieve a amxp_subproc_t for a child process using it's process identifier.
Definition: amxp_subproc.c:402
Child process information structure.
Definition: amxp_subproc.h:87

Variable Documentation

◆ amxp_subprocs

amxc_llist_t amxp_subprocs
static

Definition at line 79 of file amxp_subproc.c.