utils: Add convenience function for setting fd flags
authorSean Bright <sean.bright@gmail.com>
Thu, 7 Dec 2017 15:52:39 +0000 (10:52 -0500)
committerSean Bright <sean.bright@gmail.com>
Fri, 8 Dec 2017 19:28:04 +0000 (13:28 -0600)
There are many places in the code base where we ignore the return value
of fcntl() when getting/setting file descriptior flags. This patch
introduces a convenience function that allows setting or clearing file
descriptor flags and will also log an error on failure for later
analysis.

Change-Id: I8b81901e1b1bd537ca632567cdb408931c6eded7

17 files changed:
apps/app_ices.c
channels/chan_phone.c
channels/vgrabbers.c
codecs/codec_dahdi.c
include/asterisk/utils.h
main/alertpipe.c
main/asterisk.c
main/iostream.c
main/tcptls.c
main/udptl.c
main/utils.c
res/res_agi.c
res/res_http_websocket.c
res/res_musiconhold.c
res/res_pktccops.c
res/res_rtp_asterisk.c
res/res_timing_pthread.c

index 4ca4b67..1194384 100644 (file)
@@ -113,7 +113,6 @@ static int ices_exec(struct ast_channel *chan, const char *data)
        int fds[2];
        int ms = -1;
        int pid = -1;
-       int flags;
        struct ast_format *oreadformat;
        struct ast_frame *f;
        char filename[256]="";
@@ -128,8 +127,7 @@ static int ices_exec(struct ast_channel *chan, const char *data)
                ast_log(LOG_WARNING, "Unable to create pipe\n");
                return -1;
        }
-       flags = fcntl(fds[1], F_GETFL);
-       fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
+       ast_fd_set_flags(fds[1], O_NONBLOCK);
        
        ast_stopstream(chan);
 
index 76891ac..832f28b 100644 (file)
@@ -1191,7 +1191,6 @@ static struct phone_pvt *mkif(const char *iface, int mode, int txgain, int rxgai
 {
        /* Make a phone_pvt structure for this interface */
        struct phone_pvt *tmp;
-       int flags;      
        
        tmp = ast_calloc(1, sizeof(*tmp));
        if (tmp) {
@@ -1224,8 +1223,7 @@ static struct phone_pvt *mkif(const char *iface, int mode, int txgain, int rxgai
                ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression);
 #endif
                tmp->mode = mode;
-               flags = fcntl(tmp->fd, F_GETFL);
-               fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
+               ast_fd_set_flags(tmp->fd, O_NONBLOCK);
                tmp->owner = NULL;
                ao2_cleanup(tmp->lastformat);
                tmp->lastformat = NULL;
index 2581740..169e59c 100644 (file)
@@ -226,12 +226,8 @@ static void *grab_v4l1_open(const char *dev, struct fbuf_t *geom, int fps)
        v->b = *geom;
        b = &v->b;      /* shorthand */
 
-       i = fcntl(fd, F_GETFL);
-       if (-1 == fcntl(fd, F_SETFL, i | O_NONBLOCK)) {
-               /* non fatal, just emit a warning */
-               ast_log(LOG_WARNING, "error F_SETFL for %s [%s]\n",
-                       dev, strerror(errno));
-       }
+       ast_fd_set_flags(fd, O_NONBLOCK);
+
        /* set format for the camera.
         * In principle we could retry with a different format if the
         * one we are asking for is not supported.
index efb0168..941bb1f 100644 (file)
@@ -613,7 +613,6 @@ static int dahdi_translate(struct ast_trans_pvt *pvt, uint32_t dst_dahdi_fmt, ui
        /* Request translation through zap if possible */
        int fd;
        struct codec_dahdi_pvt *dahdip = pvt->pvt;
-       int flags;
        int tried_once = 0;
        const char *dev_filename = "/dev/dahdi/transcode";
 
@@ -659,11 +658,7 @@ retry:
                return -1;
        }
 
-       flags = fcntl(fd, F_GETFL);
-       if (flags > - 1) {
-               if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
-                       ast_log(LOG_WARNING, "Could not set non-block mode!\n");
-       }
+       ast_fd_set_flags(fd, O_NONBLOCK);
 
        dahdip->fd = fd;
 
index 0a12b1d..c6c3407 100644 (file)
@@ -1141,4 +1141,44 @@ int ast_compare_versions(const char *version1, const char *version2);
  */
 int ast_check_ipv6(void);
 
+enum ast_fd_flag_operation {
+       AST_FD_FLAG_SET,
+       AST_FD_FLAG_CLEAR,
+};
+
+/*
+ * \brief Set flags on the given file descriptor
+ * \since 13.19
+ *
+ * If getting or setting flags of the given file descriptor fails, logs an
+ * error message.
+ *
+ * \param fd File descriptor to set flags on
+ * \param flags The flag(s) to set
+ *
+ * \return -1 on error
+ * \return 0 if successful
+ */
+#define ast_fd_set_flags(fd, flags) \
+       __ast_fd_set_flags((fd), (flags), AST_FD_FLAG_SET, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+/*
+ * \brief Clear flags on the given file descriptor
+ * \since 13.19
+ *
+ * If getting or setting flags of the given file descriptor fails, logs an
+ * error message.
+ *
+ * \param fd File descriptor to clear flags on
+ * \param flags The flag(s) to clear
+ *
+ * \return -1 on error
+ * \return 0 if successful
+ */
+#define ast_fd_clear_flags(fd, flags) \
+       __ast_fd_set_flags((fd), (flags), AST_FD_FLAG_CLEAR, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+int __ast_fd_set_flags(int fd, int flags, enum ast_fd_flag_operation op,
+       const char *file, int lineno, const char *function);
+
 #endif /* _ASTERISK_UTILS_H */
index fa6ec7b..7932a73 100644 (file)
@@ -55,17 +55,8 @@ int ast_alertpipe_init(int alert_pipe[2])
                ast_log(LOG_WARNING, "Failed to create alert pipe: %s\n", strerror(errno));
                return -1;
        } else {
-               int flags = fcntl(alert_pipe[0], F_GETFL);
-               if (fcntl(alert_pipe[0], F_SETFL, flags | O_NONBLOCK) < 0) {
-                       ast_log(LOG_WARNING, "Failed to set non-blocking mode on alert pipe: %s\n",
-                               strerror(errno));
-                       ast_alertpipe_close(alert_pipe);
-                       return -1;
-               }
-               flags = fcntl(alert_pipe[1], F_GETFL);
-               if (fcntl(alert_pipe[1], F_SETFL, flags | O_NONBLOCK) < 0) {
-                       ast_log(LOG_WARNING, "Failed to set non-blocking mode on alert pipe: %s\n",
-                               strerror(errno));
+               if (ast_fd_set_flags(alert_pipe[0], O_NONBLOCK)
+                  || ast_fd_set_flags(alert_pipe[1], O_NONBLOCK)) {
                        ast_alertpipe_close(alert_pipe);
                        return -1;
                }
index bc7ac8b..5c658d0 100644 (file)
@@ -1569,7 +1569,6 @@ static void *listener(void *unused)
        int s;
        socklen_t len;
        int x;
-       int flags;
        struct pollfd fds[1];
        for (;;) {
                if (ast_socket < 0)
@@ -1607,8 +1606,7 @@ static void *listener(void *unused)
                                                close(s);
                                                break;
                                        }
-                                       flags = fcntl(consoles[x].p[1], F_GETFL);
-                                       fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
+                                       ast_fd_set_flags(consoles[x].p[1], O_NONBLOCK);
                                        consoles[x].mute = 1; /* Default is muted, we will un-mute if necessary */
                                        /* Default uid and gid to -2, so then in cli.c/cli_has_permissions() we will be able
                                           to know if the user didn't send the credentials. */
index d918633..aaa74fa 100644 (file)
@@ -77,7 +77,7 @@ int ast_iostream_get_fd(struct ast_iostream *stream)
 
 void ast_iostream_nonblock(struct ast_iostream *stream)
 {
-       fcntl(stream->fd, F_SETFL, fcntl(stream->fd, F_GETFL) | O_NONBLOCK);
+       ast_fd_set_flags(stream->fd, O_NONBLOCK);
 }
 
 SSL *ast_iostream_get_ssl(struct ast_iostream *stream)
index a6d0538..02a2af5 100644 (file)
@@ -223,7 +223,7 @@ void *ast_tcptls_server_root(void *data)
        pthread_t launched;
 
        for (;;) {
-               int i, flags;
+               int i;
 
                if (desc->periodic_fn) {
                        desc->periodic_fn(desc);
@@ -261,8 +261,7 @@ void *ast_tcptls_server_root(void *data)
                        close(fd);
                        continue;
                }
-               flags = fcntl(fd, F_GETFL);
-               fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+               ast_fd_clear_flags(fd, O_NONBLOCK);
 
                tcptls_session->stream = ast_iostream_from_fd(&fd);
                if (!tcptls_session->stream) {
@@ -514,7 +513,6 @@ void ast_ssl_teardown(struct ast_tls_config *cfg)
 struct ast_tcptls_session_instance *ast_tcptls_client_start(struct ast_tcptls_session_instance *tcptls_session)
 {
        struct ast_tcptls_session_args *desc;
-       int flags;
 
        if (!(desc = tcptls_session->parent)) {
                goto client_start_error;
@@ -528,8 +526,7 @@ struct ast_tcptls_session_instance *ast_tcptls_client_start(struct ast_tcptls_se
                goto client_start_error;
        }
 
-       flags = fcntl(desc->accept_fd, F_GETFL);
-       fcntl(desc->accept_fd, F_SETFL, flags & ~O_NONBLOCK);
+       ast_fd_clear_flags(desc->accept_fd, O_NONBLOCK);
 
        if (desc->tls_cfg) {
                desc->tls_cfg->enabled = 1;
@@ -621,7 +618,6 @@ error:
 
 void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
 {
-       int flags;
        int x = 1;
        int tls_changed = 0;
        int sd_socket;
@@ -740,8 +736,7 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
        }
 
 systemd_socket_activation:
-       flags = fcntl(desc->accept_fd, F_GETFL);
-       fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK);
+       ast_fd_set_flags(desc->accept_fd, O_NONBLOCK);
        if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) {
                ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n",
                        desc->name,
index 853e43c..d982f6b 100644 (file)
@@ -1012,7 +1012,6 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct ast_sched_context *sched, s
        int x;
        int startplace;
        int i;
-       long int flags;
        RAII_VAR(struct udptl_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
 
        if (!cfg || !cfg->general) {
@@ -1043,8 +1042,7 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct ast_sched_context *sched, s
                ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
                return NULL;
        }
-       flags = fcntl(udptl->fd, F_GETFL);
-       fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK);
+       ast_fd_set_flags(udptl->fd, O_NONBLOCK);
 
 #ifdef SO_NO_CHECK
        if (cfg->general->nochecksums)
index c553207..931a1ae 100644 (file)
@@ -2749,3 +2749,37 @@ int ast_compare_versions(const char *version1, const char *version2)
        }
        return extra[0] - extra[1];
 }
+
+int __ast_fd_set_flags(int fd, int flags, enum ast_fd_flag_operation op,
+       const char *file, int lineno, const char *function)
+{
+       int f;
+
+       f = fcntl(fd, F_GETFL);
+       if (f == -1) {
+               ast_log(__LOG_ERROR, file, lineno, function,
+                       "Failed to get fcntl() flags for file descriptor: %s\n", strerror(errno));
+               return -1;
+       }
+
+       switch (op) {
+       case AST_FD_FLAG_SET:
+               f |= flags;
+               break;
+       case AST_FD_FLAG_CLEAR:
+               f &= ~flags;
+               break;
+       default:
+               ast_assert(0);
+               break;
+       }
+
+       f = fcntl(fd, F_SETFL, f);
+       if (f == -1) {
+               ast_log(__LOG_ERROR, file, lineno, function,
+                       "Failed to set fcntl() flags for file descriptor: %s\n", strerror(errno));
+               return -1;
+       }
+
+       return 0;
+}
index 13af48f..85914c0 100644 (file)
@@ -2046,7 +2046,7 @@ static int handle_connection(const char *agiurl, const struct ast_sockaddr addr,
        FastAGI defaults to port 4573 */
 static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds)
 {
-       int s = 0, flags;
+       int s = 0;
        char *host, *script;
        int num_addrs = 0, i = 0;
        struct ast_sockaddr *addrs;
@@ -2076,14 +2076,7 @@ static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds)
                        continue;
                }
 
-               if ((flags = fcntl(s, F_GETFL)) < 0) {
-                       ast_log(LOG_WARNING, "fcntl(F_GETFL) failed: %s\n", strerror(errno));
-                       close(s);
-                       continue;
-               }
-
-               if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
-                       ast_log(LOG_WARNING, "fnctl(F_SETFL) failed: %s\n", strerror(errno));
+               if (ast_fd_set_flags(s, O_NONBLOCK)) {
                        close(s);
                        continue;
                }
@@ -2249,9 +2242,8 @@ static enum agi_result launch_script(struct ast_channel *chan, char *script, int
                        close(toast[1]);
                        return AGI_RESULT_FAILURE;
                }
-               res = fcntl(audio[1], F_GETFL);
-               if (res > -1)
-                       res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK);
+
+               res = ast_fd_set_flags(audio[1], O_NONBLOCK);
                if (res < 0) {
                        ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
                        close(fromast[0]);
index c1f9a29..baaa40f 100644 (file)
@@ -951,17 +951,11 @@ static struct ast_http_uri websocketuri = {
 /*! \brief Simple echo implementation which echoes received text and binary frames */
 static void websocket_echo_callback(struct ast_websocket *session, struct ast_variable *parameters, struct ast_variable *headers)
 {
-       int flags, res;
+       int res;
 
        ast_debug(1, "Entering WebSocket echo loop\n");
 
-       if ((flags = fcntl(ast_websocket_fd(session), F_GETFL)) == -1) {
-               goto end;
-       }
-
-       flags |= O_NONBLOCK;
-
-       if (fcntl(ast_websocket_fd(session), F_SETFL, flags) == -1) {
+       if (ast_fd_set_flags(ast_websocket_fd(session), O_NONBLOCK)) {
                goto end;
        }
 
index e4bb7a2..ef1b81c 100644 (file)
@@ -922,7 +922,6 @@ static struct mohclass *_get_mohbyname(const char *name, int warn, int flags, co
 static struct mohdata *mohalloc(struct mohclass *cl)
 {
        struct mohdata *moh;
-       long flags;
 
        if (!(moh = ast_calloc(1, sizeof(*moh))))
                return NULL;
@@ -934,10 +933,8 @@ static struct mohdata *mohalloc(struct mohclass *cl)
        }
 
        /* Make entirely non-blocking */
-       flags = fcntl(moh->pipe[0], F_GETFL);
-       fcntl(moh->pipe[0], F_SETFL, flags | O_NONBLOCK);
-       flags = fcntl(moh->pipe[1], F_GETFL);
-       fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK);
+       ast_fd_set_flags(moh->pipe[0], O_NONBLOCK);
+       ast_fd_set_flags(moh->pipe[1], O_NONBLOCK);
 
        moh->f.frametype = AST_FRAME_VOICE;
        moh->f.subclass.format = cl->format;
index e8d266c..156c49d 100644 (file)
@@ -648,7 +648,7 @@ static struct cops_gate *cops_gate_cmd(int cmd, struct cops_cmts *cmts,
 
 static int cops_connect(char *host, char *port)
 {
-       int s, sfd = -1, flags;
+       int s, sfd = -1;
        struct addrinfo hints;
        struct addrinfo *rp;
        struct addrinfo *result;
@@ -674,8 +674,7 @@ static int cops_connect(char *host, char *port)
                if (sfd == -1) {
                        ast_log(LOG_WARNING, "Failed socket\n");
                }
-               flags = fcntl(sfd, F_GETFL);
-               fcntl(sfd, F_SETFL, flags | O_NONBLOCK);
+               ast_fd_set_flags(sfd, O_NONBLOCK);
 #ifdef HAVE_SO_NOSIGPIPE
                setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, &trueval, sizeof(trueval));
 #endif
index 5aeb791..16eb7dd 100644 (file)
@@ -3048,8 +3048,7 @@ static int create_new_socket(const char *type, int af)
                }
                ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
        } else {
-               long flags = fcntl(sock, F_GETFL);
-               fcntl(sock, F_SETFL, flags | O_NONBLOCK);
+               ast_fd_set_flags(sock, O_NONBLOCK);
 #ifdef SO_NO_CHECK
                if (nochecksums) {
                        setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
index 09952f9..f520796 100644 (file)
@@ -130,9 +130,7 @@ static void *pthread_timer_open(void)
        }
 
        for (i = 0; i < ARRAY_LEN(timer->pipe); ++i) {
-               int flags = fcntl(timer->pipe[i], F_GETFL);
-               flags |= O_NONBLOCK;
-               fcntl(timer->pipe[i], F_SETFL, flags);
+               ast_fd_set_flags(timer->pipe[i], O_NONBLOCK);
        }
        
        ao2_lock(pthread_timers);