Why is _GNU_SOURCE macro required for pthread_mutexattr_settype() while it is in POSIX/IEEE standard?
Asked Answered
K

3

11

I have written a multithread server program in C, which echoes back all the data that a client sends.

Initially, I used poll() function in my program to detect POLLRDHUP event, for that I defined _GNU_SOURCE macro (This event is defined here).

Later I updated my code & removed poll() function, however I forgot to remove _GNU_SOURCE macro.

Now my code is finally complete (and a little long to post, more than 250 lines). Before removing macro I was compiling my program using:

gcc multi_thread_socket_v4.c -Wall -Werror -g -lpthread -o multi_thread_socket

and it worked fine: No errors, no warnings

After I removed the macro definition, and compiled using same command-line, the output of gcc was:

multi_thread_socket_v4.c: In function ‘main’:
multi_thread_socket_v4.c:194: warning: implicit declaration of function ‘pthread_mutexattr_settype’
multi_thread_socket_v4.c:194: error: ‘PTHREAD_MUTEX_ERRORCHECK’ undeclared (first use in this function)
multi_thread_socket_v4.c:194: error: (Each undeclared identifier is reported only once
multi_thread_socket_v4.c:194: error: for each function it appears in.)

I have included all the required libraries as it worked fine initially.

I peeked into pthread.h at /usr/include/pthread.h and found out this:

/* Mutex types.  */
enum
{
  PTHREAD_MUTEX_TIMED_NP,
  PTHREAD_MUTEX_RECURSIVE_NP,
  PTHREAD_MUTEX_ERRORCHECK_NP,
  PTHREAD_MUTEX_ADAPTIVE_NP
#ifdef __USE_UNIX98
  ,
  PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP,
  PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
  PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
  PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
#endif
#ifdef __USE_GNU
  /* For compatibility.  */
  , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP
#endif
};

and this:

#ifdef __USE_UNIX98
/* Return in *KIND the mutex kind attribute in *ATTR.  */
extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict
                      __attr, int *__restrict __kind)
     __THROW __nonnull ((1, 2));

/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL,
   PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or
   PTHREAD_MUTEX_DEFAULT).  */
extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
     __THROW __nonnull ((1));

I checked out here to check if __USE_UNIX98 is a feature test macro, but it was not there.

So please help me understanding the reasons for the error, because the function & the macro where gcc shows error are defined in POSIX standard. I do not know what more info regarding my problem will be required so please tell me, I will update my question.

Kastner answered 22/8, 2013 at 8:42 Comment(4)
The most obvious answer is that the feature is not in Posix, but only in Linux. By default, the pthread library tries to be Posix conforming.Corbitt
Also note that double-underscore macros aren't for you to use; they're reset internally. You can only use top-level macros like _GNU_SOURCE and _BSD_SOURCE to control which parts of the library are pulled in.Corbitt
@KerrekSB : But the function pthread_setattr_settype() & the macro PTHREAD_MUTEX_ERRORCHECK are POSIX standard, so why they need _GNU_SOURCE to be defined?Kastner
But they aren't standard C, so they need something to be defined ... not necessarily _GNU_SOURCE, which is a kitchen sink define that drags in lots of stuff.Bayern
B
9

You should use

#define _POSIX_C_SOURCE 200112L

if you want to use POSIX features such as pthread_mutexattr_settype ... see http://pubs.opengroup.org/onlinepubs/007904975/functions/xsh_chap02_02.html

Another possibility is

#define _XOPEN_SOURCE 700

See http://man7.org/linux/man-pages/man7/feature_test_macros.7.html and http://pubs.opengroup.org/onlinepubs/9699919799/

Setting _GNU_SOURCE includes POSIX and lots of other definitions.

P.S. I would expect that including <pthread.h> includes <features.h>, which by default defines _POSIX_C_SOURCE as 200112L, but it's possible that you have defined something that overrides that ... see /usr/include/features.h on your system for details of the symbols and their usage.

Bayern answered 22/8, 2013 at 9:41 Comment(4)
Got your point, will read them. By the way this link I found is more recent standard revision.Kastner
@nishant That link is within the one I gave. I don't really think you need to read them, you just need to provide the defines. What I'm doing here is answering your question.Bayern
Thanks, although _XOPEN_SOURCE 700 did the trick (so did the _GNU_SOURCE). but won't it affect other functions also? I mean may be other functions start behaving differently.Kastner
@nishant Mostly it affects what symbols are visible, not behavior. You could get behavior changes if you were explicitly asking for older obsolescent versions of standards.Bayern
F
0

It doesn't, your problem likely lies elsewhere.

I just compiled a trivial program with the following content:

#include <pthread.h>

int main(int argc, char **argv)
{
    pthread_mutexattr_t attr;

    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);

    return 0;
}

This compiles perfectly with gcc -pthread -Wall -Werror a.c.

It's possible that another part of your program causes this, by eg. doing something silly like defining _PTHREAD_H, or some other minor sabotage.

You might want to try to get a minimal test case by using a tool like delta or creduce, which will probably make the problem evident.

Felicidad answered 22/8, 2013 at 9:40 Comment(5)
Your code gives same error on my machine. Machine specs: Operating System: SLES 10 SP3 x86-64.Kastner
@nishant There are other answers here. Try mine.Bayern
@nishant: That's quite strange. I've built this on a vanilla debian install. AFAIK, you shouldn't have to explicitly define any feature macros, as features.h included from pthread.h should define these if nothing else was defined (which is why this compiles here, which I just checked using gcc -E -fdirectives-only.)Felicidad
I'll also note that setting some things will break this, eg. defining __STRICT_ANSI__ (by way of the -ansi flag), or _POSIX_SOURCE or _POSIX_C_SOURCE. (in my case, this ends up setting __USE_XOPEN2K8 which enables the function)Felicidad
I studied the output of gcc file.c -E -fdirectives-only but nowhere there, __USE_UNIX98 was defined. However after #define _XOPEN_SOURCE 700 this line #define __USE_UNIX98 was there at the end.Kastner
H
0

When you're using old libraries (e.g. 2.1.x) you should use

#define __USE_UNIX98

Using a macro beginning with "__" it's not usually a good idea, but sometimes it's the only way... see also this discussion

Hiatus answered 22/3, 2016 at 9:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.