Asterisk - The Open Source Telephony Project  18.5.0
alertpipe.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2017, Sean Bright
5  *
6  * Sean Bright <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Alert Pipe API
22  *
23  * \author Sean Bright
24  */
25 
26 #include "asterisk.h"
27 
28 #include <unistd.h>
29 #include <fcntl.h>
30 
31 #ifdef HAVE_EVENTFD
32 # include <sys/eventfd.h>
33 #endif
34 
35 #include "asterisk/alertpipe.h"
36 #include "asterisk/logger.h"
37 
39 {
40 #ifdef HAVE_EVENTFD
41 
42  int fd = eventfd(0, EFD_NONBLOCK | EFD_SEMAPHORE);
43  if (fd > -1) {
44  alert_pipe[0] = alert_pipe[1] = fd;
45  return 0;
46  }
47 
48  ast_log(LOG_WARNING, "Failed to create alert pipe with eventfd(), falling back to pipe(): %s\n",
49  strerror(errno));
50  ast_alertpipe_clear(alert_pipe);
51 
52 #endif
53 
54 #ifdef HAVE_PIPE2
55 
56  if (pipe2(alert_pipe, O_NONBLOCK)) {
57  ast_log(LOG_WARNING, "Failed to create alert pipe: %s\n", strerror(errno));
58  return -1;
59  }
60 
61 #else
62 
63  if (pipe(alert_pipe)) {
64  ast_log(LOG_WARNING, "Failed to create alert pipe: %s\n", strerror(errno));
65  return -1;
66  } else {
67  if (ast_fd_set_flags(alert_pipe[0], O_NONBLOCK)
68  || ast_fd_set_flags(alert_pipe[1], O_NONBLOCK)) {
69  ast_alertpipe_close(alert_pipe);
70  return -1;
71  }
72  }
73 
74 #endif
75 
76  return 0;
77 }
78 
80 {
81 #ifdef HAVE_EVENTFD
82 
83  if (alert_pipe[0] == alert_pipe[1]) {
84  if (alert_pipe[0] > -1) {
85  close(alert_pipe[0]);
86  ast_alertpipe_clear(alert_pipe);
87  }
88  return;
89  }
90 
91 #endif
92 
93  if (alert_pipe[0] > -1) {
94  close(alert_pipe[0]);
95  }
96  if (alert_pipe[1] > -1) {
97  close(alert_pipe[1]);
98  }
99  ast_alertpipe_clear(alert_pipe);
100 }
101 
103 {
104  uint64_t tmp;
105 
106  if (!ast_alertpipe_readable(alert_pipe)) {
107  return AST_ALERT_NOT_READABLE;
108  }
109 
110  if (read(alert_pipe[0], &tmp, sizeof(tmp)) < 0) {
111  if (errno != EINTR && errno != EAGAIN) {
112  ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
113  return AST_ALERT_READ_FAIL;
114  }
115  }
116 
117  return AST_ALERT_READ_SUCCESS;
118 }
119 
121 {
122  uint64_t tmp = 1;
123 
124  if (!ast_alertpipe_writable(alert_pipe)) {
125  errno = EBADF;
126  return 0;
127  }
128 
129  /* preset errno in case returned size does not match */
130  errno = EPIPE;
131  return write(alert_pipe[1], &tmp, sizeof(tmp)) != sizeof(tmp);
132 }
133 
135 {
136  int bytes_read;
137  uint64_t tmp[16];
138 
139  if (!ast_alertpipe_readable(alert_pipe)) {
140  return AST_ALERT_NOT_READABLE;
141  }
142 
143  /* Read the alertpipe until it is exhausted. */
144  for (;;) {
145  bytes_read = read(alert_pipe[0], tmp, sizeof(tmp));
146  if (bytes_read < 0) {
147  if (errno == EINTR) {
148  continue;
149  }
150  if (errno == EAGAIN || errno == EWOULDBLOCK) {
151  /*
152  * Would block so nothing left to read.
153  * This is the normal loop exit.
154  */
155  break;
156  }
157  ast_log(LOG_WARNING, "read() failed flushing alertpipe: %s\n",
158  strerror(errno));
159  return AST_ALERT_READ_FAIL;
160  }
161  if (!bytes_read) {
162  /* Read nothing so we are done */
163  break;
164  }
165  }
166 
167  return AST_ALERT_READ_SUCCESS;
168 }
Asterisk main include file. File version handling, generic pbx functions.
#define LOG_WARNING
Definition: logger.h:274
static int tmp()
Definition: bt_open.c:389
void ast_alertpipe_close(int alert_pipe[2])
Close an alert pipe.
Definition: alertpipe.c:79
int ast_alertpipe_readable(int alert_pipe[2])
Determine if the alert pipe is readable.
Definition: alertpipe.h:112
void ast_alertpipe_clear(int alert_pipe[2])
Sets the alert pipe file descriptors to default values.
Definition: alertpipe.h:97
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
Definition: utils.h:1009
#define ast_log
Definition: astobj2.c:42
int ast_alertpipe_writable(int alert_pipe[2])
Determine if the alert pipe is writable.
Definition: alertpipe.h:127
ast_alert_status_t ast_alertpipe_read(int alert_pipe[2])
Read an event from an alert pipe.
Definition: alertpipe.c:102
int ast_alertpipe_init(int alert_pipe[2])
Initialize an alert pipe.
Definition: alertpipe.c:38
int alert_pipe[2]
Definition: res_corosync.c:276
int errno
Support for logging to various files, console and syslog Configuration in file logger.conf.
ast_alert_status_t ast_alertpipe_flush(int alert_pipe[2])
Consume all alerts written to the alert pipe.
Definition: alertpipe.c:134
ssize_t ast_alertpipe_write(int alert_pipe[2])
Write an event to an alert pipe.
Definition: alertpipe.c:120
ast_alert_status_t
Definition: alertpipe.h:24