mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 18:55:19 +00:00 
			
		
		
		
	utils: Add convenience function for setting fd flags
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
This commit is contained in:
		| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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 */ | ||||
|   | ||||
| @@ -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; | ||||
| 		} | ||||
|   | ||||
| @@ -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. */ | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
							
								
								
									
										34
									
								
								main/utils.c
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								main/utils.c
									
									
									
									
									
								
							| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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]); | ||||
|   | ||||
| @@ -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; | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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)); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user