*
* \param f The function to be called.
* \param query Pointer to arbitrary data for the callback.
- * \param result Callback result will be stored here.
+ * \param result_handler Called for each shm area sent by the callback.
+ * \param private_result_data Passed verbatim to \a result_handler.
*
- * This function creates a shared memory area, copies the buffer pointed to by
- * \a query to that area and notifies the afs process that \a f should be
- * called ASAP.
+ * This function creates a socket for communication with the afs process and a
+ * shared memory area (sma) to which the buffer pointed to by \a query is
+ * copied. It then notifies the afs process that the callback function \a f
+ * should be executed by sending the shared memory identifier (shmid) to the
+ * socket.
+
+ * If the callback produces a result, it sends any number of shared memory
+ * identifiers back via the socket. For each such identifier received, \a
+ * result_handler is called. The contents of the sma identified by the received
+ * shmid are passed to that function as an osl object. The private_result_data
+ * pointer is passed as the second argument to \a result_handler.
*
* \return Negative, on errors, the return value of the callback function
* otherwise.
* \param argc Argument count.
* \param argv Standard argument vector.
* \param f The callback function.
- * \param result The result of the query is stored here.
+ * \param result_handler See \ref send_callback_request.
+ * \param private_result_data See \ref send_callback_request.
*
* Some commands have a couple of options that are parsed in child context for
* syntactic correctness and are stored in a special options structure for that
* \param argc The same meaning as in send_option_arg_callback_request().
* \param argv The same meaning as in send_option_arg_callback_request().
* \param f The same meaning as in send_option_arg_callback_request().
- * \param result The same meaning as in send_option_arg_callback_request().
+ * \param result_handler See \ref send_callback_request.
+ * \param private_result_data See \ref send_callback_request.
*
* This is similar to send_option_arg_callback_request(), but no options buffer
* is passed to the parent process.
* \param arg_obj Pointer to the arguments to \a f.
* \param f The callback function.
* \param max_len Don't read more than that many bytes from stdin.
- * \param result The result of the query is stored here.
+ * \param result_handler See \ref send_callback_request.
+ * \param private_result_data See \ref send_callback_request.
*
* This function is used by commands that wish to let para_server store
* arbitrary data specified by the user (for instance the add_blob family of
* commands). First, at most \a max_len bytes are read from \a fd, the result
* is concatenated with the buffer given by \a arg_obj, and the combined buffer
- * is made available to the parent process via shared memory.
+ * is made available to the afs process via the callback method. See \ref
+ * send_callback_request for details.
*
* \return Negative on errors, the return value of the underlying call to
* send_callback_request() otherwise.
free(pb.buf);
}
-int send_result(struct osl_object *result, void *private_result_data)
+/**
+ * Result handler for sending data to the para_client process.
+ *
+ * \param result The data to be sent.
+ * \param fd_ptr Pointer to the file descriptor.
+ *
+ * \return The return value of the underlying call to send_bin_buffer().
+ *
+ * \sa \ref callback_result_handler.
+ */
+int send_result(struct osl_object *result, void *fd_ptr)
{
- int fd = *(int *)private_result_data;
+ int fd = *(int *)fd_ptr;
if (!result->size)
return 1;
return send_bin_buffer(fd, result->data, result->size);
return;
st->signum = para_next_signal();
t->ret = 1;
- if (st->signum == SIGUSR1)
- return; /* ignore SIGUSR1 */
if (st->signum == SIGHUP) {
close_afs_tables();
t->ret = open_afs_tables();
static void register_signal_task(void)
{
struct signal_task *st = &signal_task_struct;
+
+ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
+ PARA_EMERG_LOG("failed to ignore SIGPIPE\n");
+ exit(EXIT_FAILURE);
+ }
+ if (signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
+ PARA_EMERG_LOG("failed to ignore SIGUSR1\n");
+ exit(EXIT_FAILURE);
+ }
st->fd = para_signal_init();
PARA_INFO_LOG("signal pipe: fd %d\n", st->fd);
para_install_sighandler(SIGINT);
para_install_sighandler(SIGTERM);
- para_install_sighandler(SIGPIPE);
para_install_sighandler(SIGHUP);
st->task.pre_select = signal_pre_select;
t->ret = 1;
}
-int pass_buffer_as_shm(char *buf, size_t size, void *private_data)
+/**
+ * Send data as shared memory to a file descriptor.
+ *
+ * \param buf The buffer holding the data to be sent.
+ * \param size The size of \a buf.
+ * \param fd_ptr A pointer to the file descriptor.
+ *
+ * This function is used as the \a max_size handler in a \ref para_buffer
+ * structure. If used this way, it is called by \ref para_printf() whenever
+ * the buffer passed to para_printf() is about to exceed its maximal size.
+ *
+ * This function creates a shared memory area large enough to hold
+ * the content given by \a buf and \a size and sends the identifier
+ * of this area to the file descriptor given by \a fd_ptr.
+ *
+ * \return Zero if \a buf is \p NULL or \a size is zero. Negative on errors,
+ * and positive on success.
+ */
+int pass_buffer_as_shm(char *buf, size_t size, void *fd_ptr)
{
- int ret, shmid, fd = *(int *)private_data;
+ int ret, shmid, fd = *(int *)fd_ptr;
void *shm;
struct callback_result *cr;
register_task(&ct->task);
}
-static void register_tasks(uint32_t cookie)
-{
- register_signal_task();
- register_command_task(cookie);
-}
-
/**
* Initialize the audio file selector process.
*
struct sched s;
int i, ret;
+ register_signal_task();
INIT_LIST_HEAD(&afs_client_list);
for (i = 0; i < NUM_AFS_TABLES; i++)
afs_tables[i].init(&afs_tables[i]);
ret = open_afs_tables();
-
- if (ret < 0) {
- PARA_EMERG_LOG("%s\n", para_strerror(-ret));
- exit(EXIT_FAILURE);
- }
+ if (ret < 0)
+ goto out;
server_socket = socket_fd;
ret = mark_fd_nonblocking(server_socket);
if (ret < 0)
- exit(EXIT_FAILURE);
+ goto out_close;
PARA_INFO_LOG("server_socket: %d, afs_socket_cookie: %u\n",
server_socket, (unsigned) cookie);
init_admissible_files(conf.afs_initial_mode_arg);
- register_tasks(cookie);
+ register_command_task(cookie);
s.default_timeout.tv_sec = 0;
s.default_timeout.tv_usec = 999 * 1000;
ret = schedule(&s);
+out_close:
+ close_afs_tables();
+out:
if (ret < 0)
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
- close_afs_tables();
exit(EXIT_FAILURE);
}