mingw64 pjsip sizeof(fd_set) always double sizeof(pj_fd_set_t) causing assertion in sock_select.c - c

I've compiled pjsip into my program that I'm writing in an msys2/mingw environment (64-bit). It compiles fine. However, when I run it in my program I'm getting an assertion
// Line 49 of ../src/pj/sock_select.c
sizeof(pj_fd_set_t)-sizeof(pj_sock_t)>=sizeof(fd_set)
Every time I run the program.
When I do some digging people talk about increasing PJ_IOQUEUE_MAX_HANDLES. So I did, and I put a printf in the function before the asserts to see what the sizes are:
// My PJ_FD_ZERO variant
PJ_DEF(void) PJ_FD_ZERO(pj_fd_set_t *fdsetp)
{
printf( "PJ_IOQUEUE_MAX_HANDLES: %d, pj_fd_set_t: %I64d, pj_sock_t: %I64d, fd_set: %I64d\n", PJ_IOQUEUE_MAX_HANDLES, sizeof(pj_fd_set_t), sizeof(pj_sock_t), sizeof(fd_set) );
PJ_CHECK_STACK();
pj_assert(sizeof(pj_fd_set_t)-sizeof(pj_sock_t) >= sizeof(fd_set));
FD_ZERO(PART_FDSET(fdsetp));
PART_COUNT(fdsetp) = 0;
}
The program will output something like this:
10:27:43.477 os_core_win32.c !pjlib 2.9 for win32 initialized
10:27:43.507 sip_endpoint.c .Creating endpoint instance...
PJ_IOQUEUE_MAX_HANDLES: 16384, pj_fd_set_t: 65552, pj_sock_t: 4, fd_set: 131080
However, when I tweak PJ_IOQUEUE_MAX_HANDLES the size of pj_fd_set_t increases as it should but! the sizeof(fd_set) also becomes slight less than DOUBLE whatever sizeof(pj_fd_set_t) is! The winsock guide says that I cannot set the size of fd_set so I am very confused how the size is getting set! I don't see anywhere in the pjsip code that this is being set.
So adjusting PJ_IOQUEUE_MAX_HANDLES is quite the losing battle.
How can I fix this so my code will stop asserting?
Some references
Bash script that I ran to configure pjsip
#!/bin/bash
JOPT=1
DEBUG=false
BUILD_ALL=true
CLEAN_BEFORE_BUILD=false
TOUCH_COMMAND="touch configure.ac aclocal.m4 configure Makefile.am Makefile.in"
while getopts ":pdj:o:c" opt; do
case $opt in
j)
JOPT="$OPTARG"
;;
c)
echo "Clean before build is set."
CLEAN_BEFORE_BUILD=true;
;;
d)
DEBUG=true
;;
o)
IFS=', ' read -r -a BUILD_OPTS <<< "${OPTARG}"
BUILD_ALL=false
for option in "${BUILD_OPTS[#]}" ; do
# Set individual
case $option in
pjsip)
BUILD_PJSIP=true;
;;
*)
echo "Unknown build option ${option}"
exit
esac
done
;;
\?)
echo "Invalid option: -${OPTARG}" >&2
exit 1
;;
:)
echo "Option -${OPTARG} requires an argument." >&2
exit 1
;;
esac
done
# Make the out
mkdir out
OUT_PREFIX="$( pwd )/out"
export PKG_CONFIG_PATH="${OUT_PREFIX}/lib/pkgconfig:${PKG_CONFIG_PATH}"
if [ "$DEBUG" = true ] ; then
MAKEFLAGS="-g -O0"
else
MAKEFLAGS="-O2"
fi
# Main directory
LIB_DIRECTORY="$(pwd)/lib"
# Descend
cd "${LIB_DIRECTORY}"
pwd
# pjsip
cd "${LIB_DIRECTORY}/pjsip"
if [ "${BUILD_ALL}" = true ] || [ "${BUILD_PJSIP}" = true ] ; then
eval $TOUCH_COMMAND
./configure CFLAGS="${MAKEFLAGS} -I${OUT_PREFIX}/include" CXXFLAGS="${MAKEFLAGS}" LDFLAGS="-L${OUT_PREFIX}/lib" \
--prefix="${OUT_PREFIX}" \
--disable-openh264 \
--disable-v4l2 \
--disable-ffmpeg \
--enable-libsamplerate \
--disable-video \
--enable-shared \
--disable-static \
--disable-libyuv \
--with-external-speex \
--with-gnutls \
|| exit
if [ "${CLEAN_BEFORE_BUILD}" = true ] ; then
make clean
fi
# Without this it breaks on msys2
make -j $JOPT dep || exit
# Make the actual
make -j $JOPT || exit
# Note, had issue with writing to //c/.../pkgconfig/libproject.pc
make install || exit
fi
The assert screenshot
--Edit--
Funny enough when I run this program the sizeof( fd_set ) is 520.
#include <winsock.h>
#include <iostream>
int main( int argc, char *argv[] )
{
std::cout <<
"sizeof( fd_set )=" << sizeof( fd_set ) << "\n"
"FD_SETSIZE=" << FD_SETSIZE << std::endl;
return( EXIT_SUCCESS );
}
Result:
sizeof( fd_set )=520
FD_SETSIZE=64

I'm that guy again answering my own question.
I think what was going on is that pjsip wasn't detecting that I was using windows with mingw despite it being detected on configure.
checking build system type... x86_64-w64-mingw32
checking host system type... x86_64-w64-mingw32
checking target system type... x86_64-w64-mingw32
I found this little nugget in the types.h
/** Socket handle. */
#if defined(PJ_WIN64) && PJ_WIN64!=0
typedef pj_int64_t pj_sock_t;
#else
typedef long pj_sock_t;
#endif
I think realized that pj_fd_set_t (which is comprised of pj_sock_t) would be smaller always than fd_set (which is comprised of fd) if the sizes are off. That would explain the proportional phenomenon. This is also because PJSIP defines FD_SETSIZE on Windows when detected.
So I just ran ./configure as I did above and then manually modified:
build.mak
build/os-auto.mak
Replacing PJ_AUTOCONF=1 with PJ_WIN32=1.
Then I manually modified the Makefile explicitly including the correct file.
include build/os-win32.mak
And then I compiled using make dep && make && make install
Finally, when I compiled it into my program it complained about implementing unicode string functions, so I looked at the file threw the error (pj/compat/string.h). I found the line #if defined(_MSC_VER) and added some more definitions as below to support MINGW macros.
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
# define strcasecmp _stricmp
# define strncasecmp _strnicmp
# define snprintf _snprintf
# define vsnprintf _vsnprintf
# define snwprintf _snwprintf
# define wcsicmp _wcsicmp
# define wcsnicmp _wcsnicmp
#else
# define stricmp strcasecmp
# define strnicmp strncasecmp
# if defined(PJ_NATIVE_STRING_IS_UNICODE) && PJ_NATIVE_STRING_IS_UNICODE!=0
# error "Implement Unicode string functions"
# endif
#endif
Then it worked!

Related

How to find all preprocessor dependencies of a specific code

Suppose there is a C/C++ header file with over ten million lines. There are lots of #ifdef and #endif statements beyond counting. What's the most efficient way to find an arbitrary line's all preprocessor dependencies? In other words, how to find all preprocessor definitions that are required to let the compiler include or ignore a block of codes that contains such line?
For example, we have the following code:
#ifdef A
#if defined(B)
#ifdef C
#else
#define X 1
#endif
#endif
#endif
In order to let the compiler include #define X 1, how do I know that I should define A and B but not C in preprocessor without manually reading the code? Or is there an efficient method to manually find all dependencies?
There is AFAIK no tool that can do this for you.
As mentioned in the comments, the correct solution is to reference the documentation. If this is some odd case where that is not an option, then you may be able to work backwards by printing out the values of each macro you are confused on. Here is a bash script I just cooked up that could automate that process for you:
deref.sh:
#!/bin/bash
if [ -z "$2" ]; then
>&2 echo "usage: $0 <file> <macro name> [<macro name> ...]"
exit 2
fi
source_file="$1"
shift
for macro in "$#"; do
play_file="$(mktemp "$(dirname "$source_file")/XXXXXX.c")"
cat "$source_file" > "$play_file"
printf '\n#ifndef %s\nUNDEFINED\n#else\n%s\n#endif' "$macro" "$macro" >> "$play_file"
printf '%s: %s\n' "$macro" "$(gcc -E "$play_file" | tail -1)"
rm "$play_file"
done
usage example...
a.c:
#define X 1
#include <stdio.h>
int main(void)
{
printf("Hello World");
}
in shell:
./deref.sh a.c X Y
X: 1
Y: UNDEFINED

How to determine when -fsanitize=memory is in use?

I want to clear a false positive on FD_ZERO and FD_SET when the memory sanitizer is in use. Clearing it is somewhat easy:
#include <sanitizer/msan_interface.h>
...
__msan_unpoison(&readfds, sizeof(readfds));
__msan_unpoison(&writefds, sizeof(writefds));
However, I don't know how to detect when the memory sanitizer is in use. That is, detect when -fsanitize=memory was specified on the command line. The preprocessor does not seem to be helping:
$ clang -dM -E -fsanitize=memory - </dev/null | egrep -i 'memory|sanitize|msan'
$
How can I determine when -fsanitize=memory is in use?
According to Konstantin Serebryany on the Memory Sanitizer mailing list, there is no preprocessor macro. The __has_feature(memory_sanitizer) should be used:
#if defined(__has_feature)
# if __has_feature(memory_sanitizer)
# define MEMORY_SANITIZER 1
# endif
#endif
...
#ifdef MEMORY_SANITIZER
# include <sanitizer/msan_interface.h>
#endif
...
#ifdef MEMORY_SANITIZER
__msan_unpoison(&readfds, sizeof(readfds));
__msan_unpoison(&writefds, sizeof(writefds));
#endif
...

How to use condition in Makefile.am

from configure.ac I have set variable ALSA=1 or nothing
./configure --enable-alsa=yes
or
./configure //nothing
and I need add source code alsa.c to Makefile.am:
__abs_top_srcdir__bin_myprogram_SOURCES+=alsa.c
I tried:
Makefile.am:
__abs_top_srcdir__bin_myprogram_SOURCES=main.c some.c anothercode.c
if ALSA
__abs_top_srcdir__bin_myprogram_SOURCES+=alsa.c
else
__abs_top_srcdir__bin_myprogram_SOURCES+=somethingelse.c
endif
and it creates
Makefile.in ending with
#ALSA_TRUE# __abs_top_srcdir__bin_myprogram_SOURCES += \
#ALSA_TRUE# alsa.c
#ALSA_FALSE# __abs_top_srcdir__bin_myprogram_SOURCES += \
#ALSA_FALSE# somethingelse.c
and Makefile ending with:
# __abs_top_srcdir__bin_myprogram_SOURCES += \
# alsa.c
__abs_top_srcdir__bin_myprogram_SOURCES += \
somethingelse.c
but I need this rows on top of this file with other source code files, because this Makefile doesn't work. I hope you understand me :)
and related part of configure.ac:
AC_ARG_ENABLE(alsa,
AS_HELP_STRING(
[--enable-alsa],
[enable alsa, default: no]),
[case "${enableval}" in
yes) alsa=true ;;
no) alsa=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-alsa]) ;;
esac],
[alsa=false])
AM_CONDITIONAL(ALSA, test x"$alsa" = x"true")
AM_COND_IF(ALSA,
AC_DEFINE(ALSA, 1, [Define to 0 for Something else]),[])
What is it wrong? May I use ALSA variable like that?Thanks you for help.
Change this:
__abs_top_srcdir__bin_myprogram_SOURCES=main.c some.c anothercode.c
if ALSA
__abs_top_srcdir__bin_myprogram_SOURCES+=alsa.c
else
__abs_top_srcdir__bin_myprogram_SOURCES+=somethingelse.c
endif
to this:
__abs_top_srcdir__bin_myprogram_SOURCES=main.c some.c anothercode.c
if ALSA
__abs_top_srcdir__bin_myprogram_SOURCES+=alsa.c
else
__abs_top_srcdir__bin_myprogram_SOURCES+=somethingelse.c
endif
and it should work.
BTW, your're also making the code in configure.ac overly complex. This'll do the same thing:
AC_ARG_ENABLE(alsa,
AS_HELP_STRING(
[--enable-alsa],
[enable alsa, default: no]))
AM_CONDITIONAL([ALSA], [test "x$enable_alsa" = "xyes"])
AM_COND_IF([ALSA],
[AC_DEFINE(ALSA, 1, [Define to 0 for Something else])],[])

Compiling C program: Dynamical type definition leads to errors

I wrote a dovecot plugin in C the last days. My source code itself seems to be quite fine, but I'm currently wondering how to compile it or how to have a more dynamical Makefile.
The problem is, that whenever I try to compile, I get the error Error: unknown type name: »uoff_t«
The problem is, that this type is defined in one referenced library in this way:
#if defined (HAVE_UOFF_T)
/* native support */
#elif defined (UOFF_T_INT)
typedef unsigned int uoff_t;
#elif defined (UOFF_T_LONG)
typedef unsigned long uoff_t;
#elif defined (UOFF_T_LONG_LONG)
typedef unsigned long long uoff_t;
#else
# error uoff_t size not set
#endif
Within dovecot's Autoconf these variables are set based on another type:
AC_CHECK_TYPE(uoff_t, [
have_uoff_t=yes
AC_DEFINE(HAVE_UOFF_T,, Define if you have a native uoff_t type)
], [
have_uoff_t=no
])
AC_TYPEOF(off_t, long int long-long)
case "$typeof_off_t" in
int)
offt_max=INT_MAX
uofft_fmt="u"
if test "$have_uoff_t" != "yes"; then
AC_DEFINE(UOFF_T_INT,, Define if off_t is int)
fi
offt_bits=`expr 8 \* $ac_cv_sizeof_int`
;;
long)
offt_max=LONG_MAX
uofft_fmt="lu"
if test "$have_uoff_t" != "yes"; then
AC_DEFINE(UOFF_T_LONG,, Define if off_t is long)
fi
offt_bits=`expr 8 \* $ac_cv_sizeof_long`
;;
"long long")
offt_max=LLONG_MAX
uofft_fmt="llu"
if test "$have_uoff_t" != "yes"; then
AC_DEFINE(UOFF_T_LONG_LONG,, Define if off_t is long long)
fi
offt_bits=`expr 8 \* $ac_cv_sizeof_long_long`
;;
*)
AC_MSG_ERROR([Unsupported off_t type])
;;
esac
So after all my question is, whether I can have this stuff in an equivalent way in my Makefile without using Automake.
My goal is to check, whether uoff_t is defined already somewhere (for HAVE_UOFF_T) or how the type off_t is defined (for the other parameters).
Any ideas, or am I missing something?
Thanks in advance!
Obviously what I tried to do seems not to be possible.
I ended up digging myself into autoconf and reusing dovecot's generic definition.
Thanks anyway!
Cheers
My first idea is that if it is a Dovecot plugin (which I know nothing about) doesn't it have to include Dovecot include files?
Wouldn't those include files have already been through the Dovecot autoconf and have all the right values for the uoff_t type?
So the first thing that I would try is to just rely on the Dovecot definition.
I suppose the other thing to do is something that I have done on occasion. Reproduce the autoconf tests inside your Makefile. But I have to warn you it tends to look really ugly. Sort of like this:
TESTOPTTMP:=$(shell mkdir -p tmp; mktemp tmp/test_opt_XXXXXXXXXX)
CFLAGS += $(shell (echo '\#include <pthread.h>'; echo '__thread int global; int main() { global = 1; return 0; }') | gcc -x c -D_GNU_SOURCE -pthread -o $(TESTOPTTMP) - >>/dev/stderr 2>&1; $(TESTOPTTMP) && echo '-DHAVE_TLS'; rm -f $(TESTOPTTMP))
That was for testing compiler support for __thread. Ugly, isn't it.

One-liner for printing out the value of a macro from a header

I have a header that defines a large number of macros, some of whom depend on other macros -- however, the dependencies are all resolved within this header.
I need a one-liner for printing out the value of a macro defined in that header.
As an example:
#define MACRO_A 0x60000000
#define MACRO_B MACRO_A + 0x00010000
//...
As a first blush:
echo MACRO_B | ${CPREPROCESSOR} --include /path/to/header
... which nearly gives me what I want:
# A number of lines that are not important
# ...
0x60000000 + 0x00010000
... however, I'm trying to keep this from ballooning into a huge sequence of "pipe it to this, then pipe it to that ...".
I've also tried this:
echo 'main(){ printf( "0x%X", MACRO_B ); }' \
| ${CPREPROCESSOR} --include /path/to/header --include /usr/include/stdio.h
... but it (the gcc compiler) complains that -E is required when processing code on standard input, so I end up having to write out to a temporary file to compile/run this.
Is there a better way?
-Brian
echo 'void main(){ printf( "0x%X", MACRO_B ); }' \
| gcc -x c --include /path/to/header --include /usr/include/stdio.h - && ./a.out
will do it in one line.
(You misread the error GCC gives when reading from stdin. You need -E or -x (needed to specify what language is expected))
Also, it's int main(), or, when you don't care like here, just drop the return type entirely. And you don't need to specify the path for stdio.h.
So slightly shorter:
echo 'main(){printf("0x%X",MACRO_B);}' \
| gcc -xc --include /path/to/header --include stdio.h - && ./a.out
What about tail -n1? Like this:
$ echo C_IRUSR | cpp --include /usr/include/cpio.h | tail -n 1
000400
How about artificially generating an error that contains your MACRO_B value in it, and then compiling the code?
I think the easiest way would be to write a small C program, include the header to that, and print the desired output. Then you can use it in your script, makefile or whatever.
echo '"EOF" EOF' | cpp --include /usr/include/stdio.h | grep EOF
prints:
"EOF" (-1)

Resources