LCOV - code coverage report
Current view: top level - crtools - util.c (source / functions) Hit Total Coverage
Test: crtools.info Lines: 184 229 80.3 %
Date: 2012-12-28 Functions: 23 23 100.0 %
Branches: 97 150 64.7 %

           Branch data     Line data    Source code
       1                 :            : #include <stdlib.h>
       2                 :            : #include <stdio.h>
       3                 :            : #include <stdarg.h>
       4                 :            : #include <string.h>
       5                 :            : #include <errno.h>
       6                 :            : #include <unistd.h>
       7                 :            : #include <stdbool.h>
       8                 :            : #include <limits.h>
       9                 :            : #include <signal.h>
      10                 :            : #include <limits.h>
      11                 :            : #include <unistd.h>
      12                 :            : #include <errno.h>
      13                 :            : #include <string.h>
      14                 :            : #include <dirent.h>
      15                 :            : #include <sys/sendfile.h>
      16                 :            : #include <fcntl.h>
      17                 :            : 
      18                 :            : #include <sys/param.h>
      19                 :            : #include <sys/types.h>
      20                 :            : #include <sys/ptrace.h>
      21                 :            : #include <sys/types.h>
      22                 :            : #include <sys/time.h>
      23                 :            : #include <sys/resource.h>
      24                 :            : #include <sys/stat.h>
      25                 :            : #include <sys/mman.h>
      26                 :            : #include <sys/vfs.h>
      27                 :            : #include <sys/ptrace.h>
      28                 :            : #include <sys/wait.h>
      29                 :            : #include <sys/resource.h>
      30                 :            : #include <sys/wait.h>
      31                 :            : 
      32                 :            : #include "compiler.h"
      33                 :            : #include "types.h"
      34                 :            : #include "list.h"
      35                 :            : #include "util.h"
      36                 :            : 
      37                 :            : #include "crtools.h"
      38                 :            : 
      39                 :            : /* /proc/PID/maps can contain not up to date information about stack */
      40                 :        698 : void mark_stack_vma(unsigned long sp, struct list_head *vma_area_list)
      41                 :            : {
      42                 :            :         struct vma_area *vma_area;
      43         [ +  - ]:      24484 :         list_for_each_entry(vma_area, vma_area_list, list) {
      44         [ +  + ]:      24484 :                 if (in_vma_area(vma_area, sp)) {
      45                 :        698 :                         vma_area->vma.status |= VMA_AREA_STACK;
      46                 :        698 :                         vma_area->vma.flags  |= MAP_GROWSDOWN;
      47                 :            : 
      48                 :            :                         /*
      49                 :            :                          * The kernel doesn't show stack guard pages on
      50                 :            :                          * proc output, so add pages here by hands.
      51                 :            :                          */
      52                 :        698 :                         vma_area->vma.start -= PAGE_SIZE;
      53                 :        698 :                         return;
      54                 :            :                 }
      55                 :            :         }
      56                 :          0 :         BUG();
      57                 :            : }
      58                 :            : 
      59                 :            : #define VMA_OPT_LEN     128
      60                 :            : 
      61                 :      12110 : static void vma_opt_str(const struct vma_area *v, char *opt)
      62                 :            : {
      63                 :      12110 :         int p = 0;
      64                 :            : 
      65                 :            : #define opt2s(_o, _s)   do {                            \
      66                 :            :                 if (v->vma.status & _o)                  \
      67                 :            :                         p += sprintf(opt + p, _s " ");        \
      68                 :            :         } while (0)
      69                 :            : 
      70                 :      12110 :         opt[p] = '\0';
      71         [ +  + ]:      12110 :         opt2s(VMA_AREA_REGULAR, "reg");
      72         [ +  + ]:      12110 :         opt2s(VMA_AREA_STACK, "stk");
      73         [ +  + ]:      12110 :         opt2s(VMA_AREA_VSYSCALL, "vsys");
      74         [ +  + ]:      12110 :         opt2s(VMA_AREA_VDSO, "vdso");
      75         [ -  + ]:      12110 :         opt2s(VMA_FORCE_READ, "frd");
      76         [ +  + ]:      12110 :         opt2s(VMA_AREA_HEAP, "heap");
      77         [ +  + ]:      12110 :         opt2s(VMA_FILE_PRIVATE, "fp");
      78         [ +  + ]:      12110 :         opt2s(VMA_FILE_SHARED, "fs");
      79         [ +  + ]:      12110 :         opt2s(VMA_ANON_SHARED, "as");
      80         [ +  + ]:      12110 :         opt2s(VMA_ANON_PRIVATE, "ap");
      81         [ +  + ]:      12110 :         opt2s(VMA_AREA_SYSVIPC, "sysv");
      82         [ -  + ]:      12110 :         opt2s(VMA_AREA_SOCKET, "sk");
      83                 :            : 
      84                 :            : #undef opt2s
      85                 :      12110 : }
      86                 :            : 
      87                 :      12110 : void pr_vma(unsigned int loglevel, const struct vma_area *vma_area)
      88                 :            : {
      89                 :            :         char opt[VMA_OPT_LEN];
      90                 :            : 
      91         [ +  - ]:      12110 :         if (!vma_area)
      92                 :      12110 :                 return;
      93                 :            : 
      94                 :      12110 :         vma_opt_str(vma_area, opt);
      95                 :      12110 :         print_on_level(loglevel, "%#lx-%#lx (%liK) prot %#x flags %#x off %#lx "
      96                 :            :                         "%s shmid: %#lx\n",
      97                 :            :                         vma_area->vma.start, vma_area->vma.end,
      98                 :      12110 :                         KBYTES(vma_area_len(vma_area)),
      99                 :            :                         vma_area->vma.prot,
     100                 :            :                         vma_area->vma.flags,
     101                 :            :                         vma_area->vma.pgoff,
     102                 :            :                         opt, vma_area->vma.shmid);
     103                 :            : }
     104                 :            : 
     105                 :      15671 : int close_safe(int *fd)
     106                 :            : {
     107                 :      15671 :         int ret = 0;
     108         [ +  + ]:      15671 :         if (*fd > -1) {
     109                 :      15491 :                 ret = close(*fd);
     110         [ +  - ]:      15491 :                 if (!ret)
     111                 :      15491 :                         *fd = -1;
     112                 :            :                 else
     113                 :          0 :                         pr_perror("Unable to close fd %d", *fd);
     114                 :            :         }
     115                 :            : 
     116                 :      15671 :         return ret;
     117                 :            : }
     118                 :            : 
     119                 :       4188 : int reopen_fd_as_safe(char *file, int line, int new_fd, int old_fd, bool allow_reuse_fd)
     120                 :            : {
     121                 :            :         int tmp;
     122                 :            : 
     123         [ +  + ]:       4188 :         if (old_fd != new_fd) {
     124                 :            : 
     125         [ +  + ]:       3025 :                 if (!allow_reuse_fd) {
     126 [ +  - ][ -  + ]:       2260 :                         if (fcntl(new_fd, F_GETFD) != -1 || errno != EBADF) {
     127         [ #  # ]:          0 :                                 if (new_fd < 3) {
     128                 :            :                                         /*
     129                 :            :                                          * Standard descriptors.
     130                 :            :                                          */
     131                 :          0 :                                         pr_warn("fd %d already in use (called at %s:%d)\n",
     132                 :            :                                                 new_fd, file, line);
     133                 :            :                                 } else {
     134                 :          0 :                                         pr_err("fd %d already in use (called at %s:%d)\n",
     135                 :            :                                                 new_fd, file, line);
     136                 :          0 :                                         return -1;
     137                 :            :                                 }
     138                 :            :                         }
     139                 :            :                 }
     140                 :            : 
     141                 :       3025 :                 tmp = dup2(old_fd, new_fd);
     142         [ -  + ]:       3025 :                 if (tmp < 0) {
     143                 :          0 :                         pr_perror("Dup %d -> %d failed (called at %s:%d)",
     144                 :            :                                   old_fd, new_fd, file, line);
     145                 :          0 :                         return tmp;
     146                 :            :                 }
     147                 :            : 
     148                 :            :                 /* Just to have error message if failed */
     149                 :       4188 :                 close_safe(&old_fd);
     150                 :            :         }
     151                 :            : 
     152                 :            :         return 0;
     153                 :            : }
     154                 :            : 
     155                 :        867 : int move_img_fd(int *img_fd, int want_fd)
     156                 :            : {
     157         [ +  + ]:        867 :         if (*img_fd == want_fd) {
     158                 :            :                 int tmp;
     159                 :            : 
     160                 :        248 :                 tmp = dup(*img_fd);
     161         [ -  + ]:        248 :                 if (tmp < 0) {
     162                 :          0 :                         pr_perror("Can't dup file");
     163                 :          0 :                         return -1;
     164                 :            :                 }
     165                 :            : 
     166                 :        248 :                 close(*img_fd);
     167                 :            : 
     168                 :        867 :                 *img_fd = tmp;
     169                 :            :         }
     170                 :            : 
     171                 :            :         return 0;
     172                 :            : }
     173                 :            : 
     174                 :            : static pid_t open_proc_pid = 0;
     175                 :            : static int open_proc_fd = -1;
     176                 :            : static int proc_dir_fd = -1;
     177                 :            : 
     178                 :       4030 : int close_pid_proc(void)
     179                 :            : {
     180                 :       4030 :         int ret = 0;
     181                 :            : 
     182         [ +  + ]:       4030 :         if (open_proc_fd >= 0)
     183                 :       1838 :                 ret = close(open_proc_fd);
     184                 :            : 
     185                 :       4030 :         open_proc_fd = -1;
     186                 :       4030 :         open_proc_pid = 0;
     187                 :            : 
     188                 :       4030 :         return ret;
     189                 :            : }
     190                 :            : 
     191                 :        953 : void close_proc()
     192                 :            : {
     193                 :        953 :         close_pid_proc();
     194         [ +  + ]:        953 :         if (proc_dir_fd > 0)
     195                 :        425 :                 close(proc_dir_fd);
     196                 :        953 :         proc_dir_fd = -1;
     197                 :        953 : }
     198                 :            : 
     199                 :         76 : int set_proc_fd(int fd)
     200                 :            : {
     201                 :         76 :         int sfd = get_service_fd(PROC_FD_OFF);
     202                 :            : 
     203                 :         76 :         sfd = dup2(fd, sfd);
     204         [ -  + ]:         76 :         if (sfd < 0) {
     205                 :          0 :                 pr_perror("Can't set proc fd\n");
     206                 :          0 :                 return -1;
     207                 :            :         }
     208                 :            : 
     209                 :         76 :         proc_dir_fd = sfd;
     210                 :            : 
     211                 :         76 :         return 0;
     212                 :            : }
     213                 :            : 
     214                 :        528 : int set_proc_mountpoint(char *path)
     215                 :            : {
     216                 :        528 :         int sfd = get_service_fd(PROC_FD_OFF), fd;
     217                 :            : 
     218                 :        528 :         close_proc();
     219                 :            : 
     220                 :        528 :         fd = open(path, O_DIRECTORY | O_RDONLY);
     221         [ -  + ]:        528 :         if (fd == -1) {
     222                 :          0 :                 pr_err("Can't open %s\n", path);
     223                 :          0 :                 return -1;
     224                 :            :         }
     225                 :            : 
     226                 :        528 :         sfd = dup2(fd, sfd);
     227                 :        528 :         close(fd);
     228         [ -  + ]:        528 :         if (sfd < 0) {
     229                 :          0 :                 pr_err("Can't set proc fd\n");
     230                 :          0 :                 return -1;
     231                 :            :         }
     232                 :            : 
     233                 :        528 :         proc_dir_fd = sfd;
     234                 :            : 
     235                 :        528 :         return 0;
     236                 :            : }
     237                 :            : 
     238                 :       7539 : inline int open_pid_proc(pid_t pid)
     239                 :            : {
     240                 :            :         char path[18];
     241                 :            :         int fd;
     242                 :            : 
     243         [ +  + ]:       7539 :         if (pid == open_proc_pid)
     244                 :       5686 :                 return open_proc_fd;
     245                 :            : 
     246                 :       1853 :         close_pid_proc();
     247                 :            : 
     248         [ +  + ]:       1853 :         if (proc_dir_fd == -1) {
     249                 :        173 :                 fd = set_proc_mountpoint("/proc");
     250         [ +  - ]:        173 :                 if (fd < 0)
     251                 :            :                         return fd;
     252                 :            :         }
     253                 :            : 
     254                 :       1853 :         snprintf(path, sizeof(path), "%d", pid);
     255                 :       1853 :         fd = openat(proc_dir_fd, path, O_RDONLY);
     256         [ -  + ]:       1853 :         if (fd < 0)
     257                 :          0 :                 pr_perror("Can't open %s", path);
     258                 :            :         else {
     259                 :       1853 :                 open_proc_fd = fd;
     260                 :       7539 :                 open_proc_pid = pid;
     261                 :            :         }
     262                 :            : 
     263                 :            :         return fd;
     264                 :            : }
     265                 :            : 
     266                 :       7372 : int do_open_proc(pid_t pid, int flags, const char *fmt, ...)
     267                 :            : {
     268                 :            :         char path[128];
     269                 :            :         va_list args;
     270                 :       7372 :         int dirfd = open_pid_proc(pid);
     271                 :            : 
     272         [ +  - ]:       7372 :         if (dirfd < 0)
     273                 :            :                 return -1;
     274                 :            : 
     275                 :       7372 :         va_start(args, fmt);
     276                 :       7372 :         vsnprintf(path, sizeof(path), fmt, args);
     277                 :       7372 :         va_end(args);
     278                 :            : 
     279                 :       7372 :         return openat(dirfd, path, flags);
     280                 :            : }
     281                 :            : 
     282                 :            : static int service_fd_rlim_cur;
     283                 :            : 
     284                 :        547 : int init_service_fd(void)
     285                 :            : {
     286                 :            :         struct rlimit rlimit;
     287                 :            : 
     288                 :            :         /*
     289                 :            :          * Service FDs are thouse that most likely won't
     290                 :            :          * conflict with any 'real-life' ones
     291                 :            :          */
     292                 :            : 
     293         [ -  + ]:        547 :         if (getrlimit(RLIMIT_NOFILE, &rlimit)) {
     294                 :          0 :                 pr_perror("Can't get rlimit");
     295                 :            :                 return -1;
     296                 :            :         }
     297                 :            : 
     298                 :        547 :         service_fd_rlim_cur = (int)rlimit.rlim_cur;
     299         [ -  + ]:        547 :         BUG_ON(service_fd_rlim_cur < SERVICE_FD_MAX);
     300                 :            : 
     301                 :            :         return 0;
     302                 :            : }
     303                 :            : 
     304                 :            : static int __get_service_fd(enum sfd_type type)
     305                 :            : {
     306                 :       6274 :         return service_fd_rlim_cur - type;
     307                 :            : }
     308                 :            : 
     309                 :       2784 : int get_service_fd(enum sfd_type type)
     310                 :            : {
     311         [ -  + ]:       2784 :         BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
     312                 :       2784 :         return __get_service_fd(type);
     313                 :            : }
     314                 :            : 
     315                 :       3490 : bool is_any_service_fd(int fd)
     316                 :            : {
     317 [ +  + ][ -  + ]:       3490 :         return fd > __get_service_fd(SERVICE_FD_MAX) &&
     318                 :            :                 fd < __get_service_fd(SERVICE_FD_MIN);
     319                 :            : }
     320                 :            : 
     321                 :        149 : bool is_service_fd(int fd, enum sfd_type type)
     322                 :            : {
     323                 :        149 :         return fd == get_service_fd(type);
     324                 :            : }
     325                 :            : 
     326                 :         22 : int copy_file(int fd_in, int fd_out, size_t bytes)
     327                 :            : {
     328                 :         22 :         ssize_t written = 0;
     329         [ +  + ]:         22 :         size_t chunk = bytes ? bytes : 4096;
     330                 :            : 
     331                 :            :         while (1) {
     332                 :            :                 ssize_t ret;
     333                 :            : 
     334                 :         32 :                 ret = sendfile(fd_out, fd_in, NULL, chunk);
     335         [ -  + ]:         32 :                 if (ret < 0) {
     336                 :          0 :                         pr_perror("Can't send data to ghost file");
     337                 :         22 :                         return -1;
     338                 :            :                 }
     339                 :            : 
     340         [ +  + ]:         32 :                 if (ret == 0) {
     341         [ -  + ]:         22 :                         if (bytes && (written != bytes)) {
     342                 :          0 :                                 pr_err("Ghost file size mismatch %lu/%lu\n",
     343                 :            :                                                 written, bytes);
     344                 :          0 :                                 return -1;
     345                 :            :                         }
     346                 :            :                         break;
     347                 :            :                 }
     348                 :            : 
     349                 :         10 :                 written += ret;
     350                 :         10 :         }
     351                 :            : 
     352                 :            :         return 0;
     353                 :            : }
     354                 :            : 
     355                 :            : #ifndef ANON_INODE_FS_MAGIC
     356                 :            : # define ANON_INODE_FS_MAGIC 0x09041934
     357                 :            : #endif
     358                 :            : 
     359                 :       1038 : bool is_anon_inode(struct statfs *statfs)
     360                 :            : {
     361                 :       1038 :         return statfs->f_type == ANON_INODE_FS_MAGIC;
     362                 :            : }
     363                 :            : 
     364                 :         20 : int is_anon_link_type(int lfd, char *type)
     365                 :            : {
     366                 :            :         char link[32], aux[32];
     367                 :            :         ssize_t ret;
     368                 :            : 
     369                 :         20 :         snprintf(aux, sizeof(aux), "/proc/self/fd/%d", lfd);
     370                 :         20 :         ret = readlink(aux, link, sizeof(link));
     371         [ -  + ]:         20 :         if (ret < 0) {
     372                 :          0 :                 pr_perror("Can't read link of fd %d\n", lfd);
     373                 :            :                 return 0;
     374                 :            :         }
     375                 :         20 :         link[ret] = 0;
     376                 :         20 :         snprintf(aux, sizeof(aux), "anon_inode:%s", type);
     377                 :         20 :         return !strcmp(link, aux);
     378                 :            : }
     379                 :            : 
     380                 :            : static void *sh_buf;
     381                 :            : static unsigned int sh_bytes_left;
     382                 :            : static size_t sh_last_size;
     383                 :            : #define SH_BUF_CHUNK    4096
     384                 :            : 
     385                 :       7126 : void *shmalloc(size_t bytes)
     386                 :            : {
     387                 :            :         void *ret;
     388                 :            : 
     389         [ -  + ]:       7126 :         if (bytes > SH_BUF_CHUNK) {
     390                 :          0 :                 pr_err("Too big shared buffer requested %lu\n", bytes);
     391                 :          0 :                 return NULL;
     392                 :            :         }
     393                 :            : 
     394         [ +  + ]:       7126 :         if (sh_bytes_left < bytes) {
     395                 :        370 :                 sh_buf = mmap(NULL, SH_BUF_CHUNK, PROT_READ | PROT_WRITE,
     396                 :            :                                 MAP_SHARED | MAP_ANON, 0, 0);
     397         [ -  + ]:        370 :                 if (sh_buf == MAP_FAILED) {
     398                 :          0 :                         pr_perror("Can't alloc shared buffer");
     399                 :          0 :                         return NULL;
     400                 :            :                 }
     401                 :            : 
     402                 :        370 :                 sh_bytes_left = SH_BUF_CHUNK;
     403                 :            :         }
     404                 :            : 
     405                 :       7126 :         ret = sh_buf;
     406                 :       7126 :         sh_buf += bytes;
     407                 :       7126 :         sh_bytes_left -= bytes;
     408                 :       7126 :         sh_last_size = bytes;
     409                 :            : 
     410                 :       7126 :         return ret;
     411                 :            : }
     412                 :            : 
     413                 :            : /* Only last chunk can be released */
     414                 :        355 : void shfree_last(void *ptr)
     415                 :            : {
     416         [ -  + ]:        355 :         BUG_ON(sh_buf - sh_last_size != ptr);
     417                 :        355 :         sh_buf -= sh_last_size;
     418                 :        355 :         sh_bytes_left += sh_last_size;
     419                 :        355 :         sh_last_size = 0;
     420                 :        355 : }
     421                 :            : 
     422                 :        152 : int run_scripts(char *action)
     423                 :            : {
     424                 :            :         struct script *script;
     425                 :        152 :         int ret = 0;
     426                 :            : 
     427         [ -  + ]:        152 :         if (setenv("CRTOOLS_SCRIPT_ACTION", action, 1)) {
     428                 :          0 :                 pr_perror("Can't set CRTOOL_SCRIPT_ACTION=%s\n", action);
     429                 :          0 :                 return -1;
     430                 :            :         }
     431                 :            : 
     432         [ -  + ]:        152 :         list_for_each_entry(script, &opts.scripts, node)
     433                 :          0 :                 ret |= system(script->path);
     434                 :            : 
     435                 :        152 :         unsetenv("CRTOOLS_SCRIPT_ACTION");
     436                 :        152 :         return ret;
     437                 :            : }
     438                 :            : 
     439                 :            : #define DUP_SAFE(fd, out)                                               \
     440                 :            :         ({                                                      \
     441                 :            :                 int ret__;                                      \
     442                 :            :                 ret__ = dup(fd);                                \
     443                 :            :                 if (ret__ == -1) {                              \
     444                 :            :                         pr_perror("dup(%d) failed", fd);      \
     445                 :            :                         goto out;                               \
     446                 :            :                 }                                               \
     447                 :            :                 ret__;                                          \
     448                 :            :         })
     449                 :            : 
     450                 :            : /*
     451                 :            :  * If "in" is negative, stdin will be closed.
     452                 :            :  * If "out" or "err" are negative, a log file descriptor will be used.
     453                 :            :  */
     454                 :        306 : int cr_system(int in, int out, int err, char *cmd, char *const argv[])
     455                 :            : {
     456                 :            :         sigset_t blockmask, oldmask;
     457                 :        306 :         int ret = -1, status;
     458                 :            :         pid_t pid;
     459                 :            : 
     460                 :        306 :         sigemptyset(&blockmask);
     461                 :        306 :         sigaddset(&blockmask, SIGCHLD);
     462         [ -  + ]:        306 :         if (sigprocmask(SIG_BLOCK, &blockmask, &oldmask) == -1) {
     463                 :          0 :                 pr_perror("Can not set mask of blocked signals");
     464                 :            :                 return -1;
     465                 :            :         }
     466                 :            : 
     467                 :        306 :         pid = fork();
     468         [ -  + ]:        753 :         if (pid == -1) {
     469                 :          0 :                 pr_perror("fork() failed\n");
     470                 :          0 :                 goto out;
     471         [ +  + ]:        753 :         } else if (pid == 0) {
     472         [ +  + ]:        306 :                 if (out < 0)
     473                 :        153 :                         out = log_get_fd();
     474         [ +  - ]:        306 :                 if (err < 0)
     475                 :        306 :                         err = log_get_fd();
     476                 :            : 
     477                 :            :                 /*
     478                 :            :                  * out, err, in should be a separate fds,
     479                 :            :                  * because reopen_fd_as() closes an old fd
     480                 :            :                  */
     481         [ +  + ]:        306 :                 if (err == out || err == in)
     482         [ -  + ]:        153 :                         err = DUP_SAFE(err, out_chld);
     483                 :            : 
     484         [ -  + ]:        306 :                 if (out == in)
     485         [ #  # ]:          0 :                         out = DUP_SAFE(out, out_chld);
     486                 :            : 
     487         [ +  + ]:        306 :                 if (in < 0) {
     488                 :        153 :                         close(STDIN_FILENO);
     489                 :            :                 } else {
     490   [ +  -  +  - ]:        306 :                         if (move_img_fd(&out, STDIN_FILENO) ||
     491                 :        153 :                             move_img_fd(&err, STDIN_FILENO))
     492                 :            :                                 goto out_chld;
     493                 :            : 
     494         [ +  - ]:        153 :                         if (reopen_fd_as_nocheck(STDIN_FILENO, in))
     495                 :            :                                 goto out_chld;
     496                 :            :                 }
     497                 :            : 
     498         [ +  - ]:        306 :                 if (move_img_fd(&err, STDOUT_FILENO))
     499                 :            :                         goto out_chld;
     500                 :            : 
     501         [ +  - ]:        306 :                 if (reopen_fd_as_nocheck(STDOUT_FILENO, out))
     502                 :            :                         goto out_chld;
     503                 :            : 
     504         [ +  - ]:        306 :                 if (reopen_fd_as_nocheck(STDERR_FILENO, err))
     505                 :            :                         goto out_chld;
     506                 :            : 
     507                 :        306 :                 execvp(cmd, argv);
     508                 :            : 
     509                 :        306 :                 pr_perror("exec failed");
     510                 :            : out_chld:
     511                 :          0 :                 _exit(1);
     512                 :            :         }
     513                 :            : 
     514                 :            :         while (1) {
     515                 :        447 :                 ret = waitpid(pid, &status, 0);
     516         [ -  + ]:        447 :                 if (ret == -1) {
     517                 :          0 :                         pr_perror("waitpid() failed");
     518                 :          0 :                         goto out;
     519                 :            :                 }
     520                 :            : 
     521         [ +  - ]:        447 :                 if (WIFEXITED(status)) {
     522         [ -  + ]:        447 :                         if (WEXITSTATUS(status))
     523                 :          0 :                                 pr_err("exited, status=%d\n", WEXITSTATUS(status));
     524                 :            :                         break;
     525         [ #  # ]:          0 :                 } else if (WIFSIGNALED(status)) {
     526                 :          0 :                         pr_err("killed by signal %d\n", WTERMSIG(status));
     527                 :          0 :                         break;
     528         [ #  # ]:          0 :                 } else if (WIFSTOPPED(status)) {
     529                 :          0 :                         pr_err("stopped by signal %d\n", WSTOPSIG(status));
     530         [ #  # ]:          0 :                 } else if (WIFCONTINUED(status)) {
     531                 :          0 :                         pr_err("continued\n");
     532                 :            :                 }
     533                 :            :         }
     534                 :            : 
     535         [ +  - ]:        447 :         ret = status ? -1 : 0;
     536                 :            : out:
     537         [ -  + ]:        447 :         if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) {
     538                 :          0 :                 pr_perror("Can not unset mask of blocked signals");
     539                 :        447 :                 BUG();
     540                 :            :         }
     541                 :            : 
     542                 :            :         return ret;
     543                 :      36594 : }

Generated by: LCOV version 1.9