Compile with -Wsuggest-attribute=malloc. We already employ this attribute extensively to help the compiler improve optimization. However, a few malloc-like functions were not yet marked with __malloc. Fix that and enable the warning to make sure that new malloc-like functions get marked. Since not all supported compilers know about this warning option, we need to check at compile time whether the option is supported. Thanks to the existing cc-option make(1) function, this is a simple one-liner for Makefile.real.
Merge branch 'maint' A single patch which adds a missing error check. * maint: audiod: Fix error checking in init_default_filters().
audiod: Fix error checking in init_default_filters(). We ignore the return value of add_filter() instead of assigning it to ret as usual, then test ret anyway. That's clearly bogus, even more so since with the old code ret can never be negative at this point, so the subsequent condition for the subsequent jump to out: is never true. This bug was introduced 13 years ago. Fixes: 081ea8699e6a309c44446884b8c3752529d96a25
Merge topic branch t/overflow into master This series implements a new memory allocation API which checks for overflows. The first part of the series just renames the main allocation functions. Later patches in the series implement allocators which take two size_t arguments (like calloc(3)) and check whether the multiplication overflows by employing the __builtin_mul_overflow() primitive supported by gcc and clang. This requires us to bump the lowest supported gcc and clang version. * refs/heads/t/overflow: build: Compile with -ftrapv. string: Introduce arr_zalloc(). string: Introduce arr_alloc(). string: Introduce arr_realloc() and check for integer overflow. string: Rename para_calloc() -> zalloc(). string: Rename para_malloc() -> alloc(). string: Overhaul para_strdup().
Merge branch 'refs/heads/t/ll' Two little cleanups related to the logging facility and two commits which add the ll command to para_server and para_audiod. The merge resulted in a conflict in afs.c due to the earlier merge of the poll topic branch which replaced all calls to select() by calls to poll(). The implementation of the ll server command introduced a new caller of select(), afs_select(), which needs to be replaced by afs_poll() to resolve the conflict. * refs/heads/t/ll: New server command: ll to change the log level at runtime. New audiod command: ll to change the log level at runtime. daemon: Kill get_loglevel_by_name(). server/audiod: Don't parse loglevel argument unnecessarily.
Switch from select(2) to poll(2). The select(2) API is kind of obsolete because it does not work for file descriptors greater or equal than 1024, The general advice is to switch to poll(2), which offers equivalent functionality and does not suffer from this restriction. This patch implements this switch. The fd sets of select(2) have one nice feature: One can determine in O(1) time whether the bit for a given fd is turned on in an fd set. For poll(2), the monitored file descriptors are organized in an array of struct pollfd. Without information about the given fd's index in the pollfd array, one can only perform a linear search which requires O(n) time, with n being the number of fds being watched. Since this would have to be done for each fd, the running time becomes quadratic in the number of monitored fds, which is bad. Keeping the pollfd array sorted would reduce that to n * log(n) at the cost of additional work at insert time. This patch implements a different approach. The scheduler now maintains an additional array of unsigned integers which map fds to indices into the pollfd array. This new index array is transparent to the individual tasks, which still simply pass one or more fds from their ->pre_monitor() method to the scheduler. The length of the index array equals the highest fd given. This might become prohibitive in theory, but should not be an issue for the time being. Care needs to be taken in order to deal with callers which ask for the readiness of an fd without having called sched_monitor_readfd() or sched_monitor_writefd() in the ->pre_monitor() step. Before the patch, thanks to the FD_ZERO() call at the beginning of each iteration of the scheduler's main loop, both sched_read_ok() and sched_write_ok() returned false for fds which were not asked to be watched. We need to keep it this way for a seamless transition. We achieve this by replacing the FD_ZERO() call by a memset(3) call which fills the index array with 0xff bytes. Both sched_read_ok() and sched_write_ok() call the new get_revents() helper, where we check the fd argument against the allocation sizes of the two arrays. If either function is called with an fd that was not asked to be monitored in the ->pre_monitor() step, the checks notice that the index of this fd, 0xffffffff, is larger than the highest open fd and we return "not ready for I/O". Another issue is the case where the same file descriptor is submitted twice in ->pre_monitor() to check for readiness with respect to both reading and writing. The code in client_comon.c currently does that. To keep it working, the scheduler needs to detect this case and re-use the existing slot in both arrays.
Rename ->{pre,post}_select methods to ->{pre,post}_monitor. The word "monitor" is neutral and continues to be correct after the switch from select(2) to poll(2). Pure rename, nothing to see here.
Hide implementation of para_fd_set(). This preparatory patch for replacing select() renames para_fd_set() to sched_fd_set(), moves it to sched.c and makes it static. All users are modified to call either of the two new public functions sched_monitor_{read,write}fd() which take a pointer to struct sched rather than an fd set pointer.
audiod: Rename handle_connect(). Now that it has the same signature as para_server's handle_connect(), doxygen gets confused and complains as follows: audiod_command.c:359: warning: argument 'accept_fd' of command @param is not found in the argument list of handle_connect(int fd) This is a false positive, but since "handle_connect" is not a very descriptive name for a public function in the first place, let's rename it.
net: Drop fd_set parameter from para_accept(). As for read_nonblock(), the parameter is dispensable because it is only used for an optimization to avoid a system call. Get rid of it because it hinders the conversion from select(2) to poll(2).
fd: Drop fd_set parameter from read_nonblock() and friends. This parameter is not necessary because its only purpose is to avoid the readv(2) system call in case it would likely return EAGAIN because we just called select(2) which reported that there is no data to read. Since the parameter is an obstacle for the conversion of the code base from select(2) to poll(2), get rid of it for the time being. If needed we can add back an equivalent optimization which checks for POLLIN after the conversion.
sched: Use integer value for select timeout. This modifies the public struct sched so that users pass in the default timeout as an integer value in milliseconds rather than a struct timeval. This simplifies the code a little and eases the transition from select(2) to poll(2) because poll(2) also takes a plain integer for the timeout. Since para_select() of fd.c now calls ms2tv() to convert the timeout back to a struct timeval, all executables which link with fd.o must also link with time.o. This was not the case for para_mixer and para_audioc, so configure.ac needs to be adjusted accordingly.
string: Introduce arr_alloc(). Change all callers of alloc() which pass a product of two integers as the allocation size to call the new function instead. This function aborts if the multiplication overflows. With arr_alloc() in place, alloc() reduces to a trivial wrapper which calls new arr_alloc() with the first argument equal to one.
string: Introduce arr_realloc() and check for integer overflow. Use __builtin_mul_overflow() for the check. This builtin was introduced in gcc-5, so we need to bump the lowest supported version. Re-implement para_realloc() as a trivial wrapper for arr_realloc() to simplify and to avoid duplicating the size check.
string: Rename para_calloc() -> zalloc(). Reword the documentation a bit since the function has never been a wrapper for calloc(3). No code changes.
string: Rename para_malloc() -> alloc(). Just because it's shorter and matches the naming of the new allocators we are about to introduce. The bulk of this patch was created with sed -i 's/para_malloc/alloc/g' *.c *.h yy/mp.y
audiod: Demote severity level of command errors. handle_connect() returning negative is a normal condition which occurs, for example, when the user specifies an invalid argument to a command. Therefore the "notice" severity level is more appropriate than the current "error" severity.
audiod: Fix time diff warning log message. The format string contains %lu to print a long unsigned, but we possibly multiply the value with -1, which can lead to output like Jun 13 13:36:37 baader (3) compute_time_diff: time diff jump: 4294808018ms Fix this by replacing the multiplication with an additional format string directive to print the leading +/- explicitly. This is easy since we already have the sign in a variable, and it avoids any integer conversion/overflow issues.
server/audiod: Don't parse loglevel argument unnecessarily. Currently the severity string (debug, info, etc.) given to --loglevel is parsed twice: Once by lopsub, which returns the loglevel as the index into the array of severity strings. We turn this index into a string and pass the string to daemon_set_loglevel() which parses the string again to turn it back into a log level value (which happens to coincide with the index value). Clean this up by letting daemon_set_loglevel() receive a log level value rather than a severity string. This also allows us to remove the now unused ENUM_STRING_VAL() macro from audiod.c.
Minor log severity adjustments. Two small changes which improve the error output of para_audiod. The first makes sure we get a message when hitting ctrl+c when audiod is running in forground mode. The second decreases the severity of the log message which is shown when a client connection terminates, since this is not necessarily an error.