#include "sort_vector.h"
#define RECEIVE_BUFFER_SIZE 16384 // How large (in bytes) pipe receiving buffer is.
-#define UNLIMITED_LOG_LEN (-RECEIVE_BUFFER_SIZE - 1) // value not reachable through a single read()
struct fd_ops;
struct fd_info {
int fd;
- int log_len;
struct fd_ops *ops;
const char *name;
void *priv_data;
struct logger_entry *(*extract_entry)(struct fd_info *fdi);
/// Transition into a state that allows reading and printing out logs
+ /// Return values > 0 mean everything went fine but we don't want to print
int (*prepare_print)(struct fd_info *fdi, int dump, list_head filters, log_format *format);
/// Clear the buffer
#include "fd_info.h"
#include "fdi_logger.h"
+#define UNLIMITED_LOG_LEN -1
+
struct logger_priv_data {
+ int log_len;
struct logger_entry *entry;
};
static int logger_prepare_print(struct fd_info *fdi, int dump, list_head filters, log_format *format)
{
assert(fdi);
+ struct logger_priv_data *const lpd = (struct logger_priv_data *)fdi->priv_data;
+ assert(lpd);
assert(format);
for (list_head iter = filters; iter; list_next(&iter))
log_add_filter_string(format, (const char *)list_at(iter));
- if (!dump)
+ if (dump == DUMP_CONTINUOUS) {
+ lpd->log_len = UNLIMITED_LOG_LEN;
return 0;
+ }
- const int log_len = logger_get_log_len(fdi->fd);
- if (log_len < 0)
- return log_len;
+ lpd->log_len = logger_get_log_len(fdi->fd);
+ if (lpd->log_len < 0)
+ return lpd->log_len;
+
+ if (lpd->log_len == 0) {
+ /* signify we don't want to get printed;
+ we can't rely on the regular removal
+ path because there won't be a read()
+ to trigger it */
+ return 1;
+ }
- fdi->log_len = log_len;
return 0;
}
parse_androidlogger_message(ale, lpd->entry, r);
add_recv_timestamp(lpd->entry);
- if (fdi->log_len > 0) {
+ if (lpd->log_len != UNLIMITED_LOG_LEN) {
/* extra 4 bytes to workaround AL driver bug:
current size (ie. log_len) is reported as if
the connection were using protocol version 2,
even if the connection is actually using v1,
whose header is 4 bytes smaller */
- fdi->log_len -= (r + 4);
+ lpd->log_len -= (r + 4);
+
+ if (lpd->log_len <= 0)
+ return 0; // emulate EOF
}
return r;
}
for (nfds = 0; nfds < fd_count; ++nfds) {
+ if (!data_fds[nfds])
+ continue;
int fd = data_fds[nfds]->fd;
ev.data.ptr = data_fds[nfds];
if (fd_set_flags(fd, O_NONBLOCK) < 0)
goto cleanup;
- if (data_fds[nfds]->log_len != 0) {
- /* can't rely on the regular log_len-based removal path
- as there would potentially be no read to trigger it */
- epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev);
- ++epoll_cnt;
- }
+ epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev);
+ ++epoll_cnt;
}
while (epoll_cnt > 0) {
if (fdi_push_log(fdi, logs, l_file))
break;
- if (r == 0 || (logs->dump != DUMP_CONTINUOUS && fdi->log_len <= 0 && fdi->log_len != UNLIMITED_LOG_LEN)) {
+ if (r == 0) {
epoll_ctl(epollfd, EPOLL_CTL_DEL, fdi->fd, NULL);
--epoll_cnt;
}
break;
case ACTION_PRINT: {
r = fdi->ops->prepare_print(fdi, logs.dump, filters, l_file.format);
+ if (r > 0) {
+ // everything went fine, but we're not printing this one
+ fdi_free(fdi);
+ fdi_ptrs[i] = NULL;
+ }
break;
} case ACTION_GETSIZE: {
uint32_t size;