8

How can I portably determine the maximum value of the pid_t type? There's no PID_MAX constant on my system.

(Note, I mean the maximum value permitted by the data type, not the de facto maximum value the system will assign to processes.)

Use case: I'm converting a user-supplied string specification of a pid to a pid_t, and want to make sure the user's input doesn't exceed the type's capacity.

pilcrow
  • 56,591
  • 13
  • 94
  • 135
  • 3
    Isn't `sizeof` sufficient for your purpose? (I'm not sure why you'd need that though, care to elaborate?) – Mat Oct 11 '12 at 14:09
  • 1
    `/proc/sys/kernel/pid_max` defines the maximum pid, which you can edit. – P.P Oct 11 '12 at 14:11
  • @KingsIndian, thanks. I mean the type's maximum, not the system's maximum value in practice. – pilcrow Oct 11 '12 at 14:14
  • @Mat, clarified in an edit. Are you proposing `#if sizeof(pid_t) ...` logic as a solution? – pilcrow Oct 11 '12 at 14:15
  • 1
    @pilcrow `#define PID_MAX ((1 << sizeof(pid_t)) - 1)`? Or if it is not guaranteed to be unsigned, `#define PID_MAX ((1 << (sizeof(pid_t) - 1)) - 1)` – Shahbaz Oct 11 '12 at 14:17
  • On linux, `pid_t` is a `typedef` to `int`. So, you can define `PID_MAX` macro as `#define PID_MAX INT_MAX` – Jack Oct 11 '12 at 14:18
  • Here you go: http://stackoverflow.com/a/1922775/1316213 – Youssef G. Oct 11 '12 at 14:18
  • Thanks for the clarification. Why do you need that in a preprocessor `#if`? If it's a runtime check data check, belongs at runtime. (@Shahbaz: POSIX says [signed integer type](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html)) – Mat Oct 11 '12 at 14:19
  • 1
    related: [How to portably convert a string into an uncommon integer type?](http://stackoverflow.com/q/437802/4279) – jfs Oct 11 '12 at 14:25
  • You may be interested in [this question](http://stackoverflow.com/questions/12762040/c-get-max-value-of-variable) and [my answer to it](http://stackoverflow.com/a/12769452/968261). – Alexey Frunze Oct 11 '12 at 14:57

4 Answers4

6

What I've done sometimes in the past is used a larger data type, and then when I convert to my smaller type, immediately convert back to the larger type and check that the value didn't change.

For example, say you used an int64_t instead, then you might have something like:

int64_t my_pid64;

/* ... parse string value into my_pid64 ... */

pid_t my_pid = (pid_t) my_pid64;
if ((int64_t) my_pid != my_pid64) /* check that value was not out of range of pid_t */
{
   /* ... handle error ... */
}

There's no great option for the larger data type to use. "long" used to be the largest primitive integer data type but that's not true on some common compilers/architectures anymore--even for Linux (see comments below). Meanwhile, the intmax_t type has poor library support. The result is that int64_t is sometimes more useful in practice.

But, basically your options for a larger data type are probably long, int64_t and intmax_t.

Steven
  • 61
  • 2
  • "it still is on Linux" - it is on Linux for x64 (same size as `long long` albeit with lower rank), but not on Linux for x86 (same size as `int`, smaller than `long long`). – Steve Jessop Oct 11 '12 at 15:19
2

POSIX (2008) says:

blksize_t, pid_t, and ssize_t shall be signed integer types.

And:

The implementation shall support one or more programming environments in which the widths of blksize_t, pid_t, size_t, ssize_t, and suseconds_t are no greater than the width of type long.

So you could convert user strings to long and then check for overflow for the pid_t type using long pid; .. pid == (pid_t)pid.

jfs
  • 399,953
  • 195
  • 994
  • 1,670
2

Steven's answer is a good approach.

But if you really want to determine the max pid_t value without relying on undefined behavior, I think your best bet is:

#include <sys/types.h>
#include <limits.h>
#include <stdlib.h>

static inline pid_t get_max_pid_t()
{
    if (sizeof(pid_t) == sizeof(short)) return SHRT_MAX;
    if (sizeof(pid_t) == sizeof(int)) return INT_MAX;
    if (sizeof(pid_t) == sizeof(long)) return LONG_MAX;
#if defined(LLONG_MAX)  // C99
    if (sizeof(pid_t) == sizeof(long long)) return LLONG_MAX;
#endif
    abort();
}

POSIX guarantees that pid_t is a signed integral type. This code assumes that the size of a signed integral type uniquely determines that type. I think this is an excellent assumption, but I am not sure whether the standard guarantees it.

Any decent compiler will inline and constant-propagate all of this into non-existence, so performance is not a concern.

(Aside: In C++ you would write std::numeric_limits<pid_t>::max() and be done with it.)

Nemo
  • 70,042
  • 10
  • 116
  • 153
0

In one of your headers:

#ifndef PID_MAX
#define PID_MAX INT_MAX // or whatever value you see fit
#endif

you can also do it based on server/OS dependent definition based on Environment variables.

Look: Similar post : Maximum PID in Linux

Community
  • 1
  • 1
जलजनक
  • 3,072
  • 2
  • 24
  • 30
  • Thanks, @SparKot. I'm not sure how your answer knows *a priori* that `pid_t` is an `int` rather than, say, a `long`. Separately, I don't think that linked post is germane: I want the data type max, not the max value the system will assign (which could be lower). – pilcrow Oct 11 '12 at 14:21