dh, the daemon helper - Unix

This is a discussion on dh, the daemon helper - Unix ; dh, the daemon helper -- run any program or shell command as a daemon. You can download the C source code, freeely available under the Apache license, Version 2.0. ftp://ftp.isp2dial.com/users/jak/src/dh/ -- Webmail for Dialup Users http://www.isp2dial.com/freeaccounts.html...

+ Reply to Thread
Page 1 of 4 1 2 3 ... LastLast
Results 1 to 20 of 70

Thread: dh, the daemon helper

  1. dh, the daemon helper


    dh, the daemon helper -- run any program or shell command as a daemon.

    You can download the C source code, freeely available under the Apache
    license, Version 2.0.

    ftp://ftp.isp2dial.com/users/jak/src/dh/



    --
    Webmail for Dialup Users
    http://www.isp2dial.com/freeaccounts.html


  2. Re: dh, the daemon helper

    John Kelly writes:
    > dh, the daemon helper -- run any program or shell command as a daemon.


    static void
    catchsig (int sn)
    {
    fprintf (stderr, "Caught signal %d\n", sn);
    (void) fflush (stderr);
    if (sn == SIGSEGV) {
    exit (EXIT_FAILURE);
    }
    }

    That's supposed to be a practical joke, right?

  3. Re: dh, the daemon helper

    Rainer Weikusat wrote:

    > John Kelly writes:
    >> dh, the daemon helper -- run any program or shell command as a daemon.

    >
    > static void
    > catchsig (int sn)
    > {
    > fprintf (stderr, "Caught signal %d\n", sn);
    > (void) fflush (stderr);
    > if (sn == SIGSEGV) {
    > exit (EXIT_FAILURE);
    > }
    > }
    >
    > That's supposed to be a practical joke, right?


    I think it's just a mistake or misunderstanding by the author.

    fprintf, fflush, and exit aren't async-signal safe.

    signal(7) usually lists the syscalls and functions which are safe in signal
    handlers.

    If you use fprintf and fflush in a signal handler you may find deadlocks, or
    segfaults result.


    --George

  4. Re: dh, the daemon helper

    GPS writes:
    > Rainer Weikusat wrote:
    >> John Kelly writes:
    >>> dh, the daemon helper -- run any program or shell command as a daemon.

    >>
    >> static void
    >> catchsig (int sn)
    >> {
    >> fprintf (stderr, "Caught signal %d\n", sn);
    >> (void) fflush (stderr);
    >> if (sn == SIGSEGV) {
    >> exit (EXIT_FAILURE);
    >> }
    >> }
    >>
    >> That's supposed to be a practical joke, right?

    >
    > I think it's just a mistake or misunderstanding by the author.


    Who would have guessed that ...

    > fprintf, fflush, and exit aren't async-signal safe.


    Yes, and stderr is unbuffered by default, hence fflush(stderr) is a
    no-op. If stderr was buffered, the buffer would automatically be
    flushed on exit and the fflush would be useless and - last but not
    least - SIGSEGV is sent by the kernel to a process which attempted an
    invalid memory access. The default action usually involves to
    terminate the process and create a core dump of it[*]. This core dump can
    then be fed into a usual debugger and used to pinpoint the exact
    location of the faulting access and how the program got there (eg, by
    providing a stack backtrace). This is very useful for fixing these
    type of issues but a signal handler like the one above prevents this
    very effectively in order to print a nonsense message.

    A related, interesting question would be: What exactly happens if the
    handler above causes another segfault to happen? On Linux 2.6.27,
    a SIGSEGV generated by a SIGSEGV handler causes the default action to
    be enforced, ie it is very possible that the handler wouldn't even
    "work" as intended but only conceal the location of the original problem.

    In short: The code excerpt above is a highly condensed demonstration
    of utter cluelessness.

    [*] This very handy feature is typically disabled by 'current'
    Linux-distribution, either to conceal the bugginess of the
    software or because nobody wants to (or knows how to) fix it,
    anyway.

  5. Re: dh, the daemon helper

    On Oct 28, 6:44*pm, Rainer Weikusat wrote:

    > In short: The code excerpt above is a highly condensed demonstration
    > of utter cluelessness.


    I'll try to fix it up. Thanks for the friendly advice.


  6. Re: dh, the daemon helper

    Rainer Weikusat writes:

    > ... last but not
    >least - SIGSEGV is sent by the kernel to a process which attempted an
    >invalid memory access. The default action usually involves to
    >terminate the process and create a core dump of it[*].

    [snip]

    > [*] This very handy feature is typically disabled by 'current'
    > Linux-distribution, either to conceal the bugginess of the
    > software or because nobody wants to (or knows how to) fix it,
    > anyway.


    This is done for a very simple reason. A significant majority of
    the users of such distributions don't really care for core dumps
    filling their filesystem (and a poorly written daemon could quickly
    fill a filesystem with fairly useless core files).

    Developers (and end users) who really want the core file can set the
    core file limit appropriately through pam, /etc/profile or .profile.

    This came about because of the addition of the pid to the corefile
    name. Prior to this, a new corefile would overwrite any other in
    the same directory. With the addition of the pid (which is a configurable
    kernel option), the potential for filling a filesystem with corefiles
    became much greater, thus the distros set the default core file size to zero.

    scott

  7. Re: dh, the daemon helper

    Scott Lurndal wrote:

    > Rainer Weikusat writes:
    >
    >> ... last but not
    >>least - SIGSEGV is sent by the kernel to a process which attempted an
    >>invalid memory access. The default action usually involves to
    >>terminate the process and create a core dump of it[*].

    > [snip]
    >
    >>[*] This very handy feature is typically disabled by 'current'
    >>Linux-distribution, either to conceal the bugginess of the
    >> software or because nobody wants to (or knows how to) fix it,
    >> anyway.

    >
    > This is done for a very simple reason. A significant majority of
    > the users of such distributions don't really care for core dumps
    > filling their filesystem (and a poorly written daemon could quickly
    > fill a filesystem with fairly useless core files).
    >
    > Developers (and end users) who really want the core file can set the
    > core file limit appropriately through pam, /etc/profile or .profile.
    >
    > This came about because of the addition of the pid to the corefile
    > name. Prior to this, a new corefile would overwrite any other in
    > the same directory. With the addition of the pid (which is a
    > configurable kernel option), the potential for filling a filesystem with
    > corefiles became much greater, thus the distros set the default core file
    > size to zero.


    Users should learn how to get a backtrace from a core file, and help fix the
    problem. When a core is generated from an abort(), SIGSEGV, or failed
    assert() the backtrace should really be sent to the developer(s). Either a
    bt or bt full, assuming some symbols.

    I know that users don't generally understand core files. But we expect them
    to understand widgets and other things, why couldn't they learn?

    I know that KDE had a sort of bug sending tool that would gather a backtrace
    at one point, after a SIGSEGV. Last time I used it I found that the tool
    would segfault itself quite often. The idea was nice, even though it was
    probably poorly implemented.

    I'm not fond of the Ubuntu/GNU/Linux naming convention for core files that
    you mentioned. NetBSD for instance names the core for the program foo,
    foo.core. That makes more sense to me than the defaults Ubuntu uses of
    core.pid, and the previous name of core.

    George

  8. Re: dh, the daemon helper

    On Oct 28, 5:51*pm, GPS wrote:

    > > static void
    > > catchsig (int sn)
    > > {
    > > * * fprintf (stderr, "Caught signal %d\n", sn);
    > > * * (void) fflush (stderr);
    > > * * if (sn == SIGSEGV) {
    > > * * * * exit (EXIT_FAILURE);
    > > * * }
    > > }

    >
    > fprintf, fflush, and exit aren't async-signal safe.


    Thanks, George.

    I changed exit to _exit and removed fprintf from the signal handler.
    And I set SIGSEGV and SIGBUS to SIG_DFL, so errors causing core dumps
    won't be obscured.

    I also found a bug in the STDOUT file lock. The lock was lost when the
    daemon closed STDOUT. Replacing fcntl with flock fixed that.

    To all, thanks for your criticism. I was hoping for more review, but
    it seems only two people followed the link to look at the code. I
    guess Usenet is in delcine. How sad.

    ftp://ftp.isp2dial.com/users/jak/src/dh/

    --
    Webmail for Dialup Users
    http://www.isp2dial.com/freeaccounts.html


  9. Re: dh, the daemon helper

    GPS writes:

    >I'm not fond of the Ubuntu/GNU/Linux naming convention for core files that
    >you mentioned. NetBSD for instance names the core for the program foo,
    >foo.core. That makes more sense to me than the defaults Ubuntu uses of
    >core.pid, and the previous name of core.


    First, the 'core.pid' naming convention predates linux by a few years (SVR4
    introduced it).

    Second, naming 'foo.core' is no better than 'core'. Subsequent core dumps from
    'foo' will overwrite the core file; something that is much less likely to happen
    by using the pid. Using file(1) on the core file will tell what program coredumped.

    scott

  10. Re: dh, the daemon helper

    scott@slp53.sl.home (Scott Lurndal) writes:

    > GPS writes:
    >
    >>I'm not fond of the Ubuntu/GNU/Linux naming convention for core files
    >>that you mentioned. NetBSD for instance names the core for the
    >>program foo, foo.core. That makes more sense to me than the defaults
    >>Ubuntu uses of core.pid, and the previous name of core.

    >
    > First, the 'core.pid' naming convention predates linux by a few years
    > (SVR4 introduced it).
    >
    > Second, naming 'foo.core' is no better than 'core'. Subsequent core
    > dumps from 'foo' will overwrite the core file; something that is much
    > less likely to happen by using the pid. Using file(1) on the core
    > file will tell what program coredumped.


    Then there's FreeBSD, which has the best of both worlds, and names it
    "foo.pid.core".

  11. Re: dh, the daemon helper

    On Wed, 29 Oct 2008 11:12:11 -0700, Nate Eldredge wrote:
    >scott@slp53.sl.home (Scott Lurndal) writes:
    >>GPS writes:
    >>>I'm not fond of the Ubuntu/GNU/Linux naming convention for core files
    >>>that you mentioned. NetBSD for instance names the core for the
    >>>program foo, foo.core. That makes more sense to me than the defaults
    >>>Ubuntu uses of core.pid, and the previous name of core.

    >>
    >> First, the 'core.pid' naming convention predates linux by a few years
    >> (SVR4 introduced it).
    >>
    >> Second, naming 'foo.core' is no better than 'core'. Subsequent core
    >> dumps from 'foo' will overwrite the core file; something that is much
    >> less likely to happen by using the pid. Using file(1) on the core
    >> file will tell what program coredumped.

    >
    > Then there's FreeBSD, which has the best of both worlds, and names it
    > "foo.pid.core".


    The default is still `%N.core', and it should be visible through the
    normal sysctl interface:

    $ sysctl kern.corefile
    kern.corefile: %N.core

    The core(5) manpage describes other format letters, like %U (uid) and %P
    (pid). It even includes an example for setting up per-user core dump
    areas under `/var/coredumps'


  12. Re: dh, the daemon helper

    On Oct 28, 12:27 am, John Kelly wrote:
    > dh, the daemon helper -- run any program or shell command as a daemon.
    >
    > You can download the C source code, freeely available under the Apache
    > license, Version 2.0.
    >
    > ftp://ftp.isp2dial.com/users/jak/src/dh/


    Hi John,

    I downloaded the source file (dh.c) located in that ftp dir and I have
    some comments on your code

    First of all, you use perror/exit a lot. I'd write a function/macro if
    I were you.

    line 43,44 it wouldn't be bad if you had a comment explaining those
    magic numbers.
    line 52 I think most C programmers prefer const char [] over char
    const [] (no actual difference)
    line 66,74 that should be isspace((unsigned char)**ts). is* and to*
    functions expect a positive integer or EOF, and char may be signed.
    line 62-81 can be replaced with keep = strtok(*ts, " \n\t\v\f\r");
    if(keep) *ts = keep; strtok(NULL, " \n\t\v\f\r"); with only difference
    that it won't behave exactly the same if the implementation has more
    than the minimum characters in the space character class. (see IEEE
    1003.1, 2004: 7.3.1 LC_CTYPE). Since I don't like either solution I
    might've considered to write a map function, and use isspace.
    line 143,156 can be replaced with if(lockname[0] == 0). There's no
    reason to process the whole string. also line 369
    line 155 IMHO the parentheses in the expression &(argv[optind])
    should be removed, like: trim(&argv[optind])

    I'm curious how your code works since in line 161 you exit if usage is
    non-zero, and at that point it can't have the value 0.
    I haven't compiled it so I might be missing something.

    line 177-213 should be replaced with some loop.
    line 214 the cast is not needed. It'd be better if you just had
    open_max a long instead of an int though.
    line 225-226 change the conversion specifier from u to d and remove
    the (unsigned int) cast. There's no benifit.
    line 353 you have several memory leaks after this line, since you
    do not free the return value of strdup on error.
    line 395,395 can be replaced with a simple free(exectemp); free(NULL)
    is defined to do nothing.
    line 473,478 getpid returns a pid_t, which might not be int (it's
    allowed to be any signed integer type). Use printf("%ld",
    (long)getpid());
    (you won't find any systems that have pid_t's with values bigger than
    2^31-1 but LONG_MAX at 2^31-1 - and even then, your process must have
    such process id, which would give you implementation-defined behavior
    or an implementation-defined signal)

    Lastly, I think you're overly verbose with error messages and error
    checking.

    This is not a complete overview of your code; there might be more
    bugs.

    HTH

  13. Re: dh, the daemon helper

    vippstar@gmail.com writes:

    [...]

    > line 52 I think most C programmers prefer const char [] over char
    > const [] (no actual difference)


    The 'actual difference' is that const xyz with xyz being the name of
    some type is a special case, while const ordinarily binds to the
    closest thing left of it, ie char const * is a pointer to a constant
    array of char and char * const is a constant pointer to an array of
    char.

    > line 66,74 that should be isspace((unsigned char)**ts). is* and to*
    > functions expect a positive integer or EOF, and char may be signed.


    The value shall be that of an unsigned char and - as usual with C - it
    doesn't matter where it came from.


    [...]

    > line 155 IMHO the parentheses in the expression &(argv[optind])
    > should be removed, like: trim(&argv[optind])


    The Right Thing[tm] would be to do away with all of the decoration and
    write argv + optind when argv + optind is meant.

    > line 353 you have several memory leaks after this line, since you
    > do not free the return value of strdup on error.


    Since programming initially running as this process is supposed to go
    away 'soon' (it's only purpose is to start another program), there is
    no point in returning memory to the malloc heap.

    > line 395,395 can be replaced with a simple free(exectemp); free(NULL)
    > is defined to do nothing.


    Then why call it?

    > line 473,478 getpid returns a pid_t, which might not be int (it's
    > allowed to be any signed integer type). Use printf("%ld",
    > (long)getpid());


    pid_t is required to be a signed integer type and all actual process
    IDs are required to be positive.

    [...]

    > This is not a complete overview of your code; there might be more
    > bugs.


    Instead of only "but that's not the way I would have done it", there
    could additionally be bugs.

  14. Re: dh, the daemon helper

    On Nov 1, 7:11 pm, Rainer Weikusat wrote:
    > vipps...@gmail.com writes:
    >
    > [...]
    >
    > > line 52 I think most C programmers prefer const char [] over char
    > > const [] (no actual difference)

    >
    > The 'actual difference' is that const xyz with xyz being the name of
    > some type is a special case, while const ordinarily binds to the
    > closest thing left of it, ie char const * is a pointer to a constant
    > array of char and char * const is a constant pointer to an array of
    > char.


    You're wrong, const char [] and char const [] are exactly the same.
    I did not claim anything about const char * and char * const.
    The equivalent would be char const * and const char *. (not char *
    const)

    > > line 66,74 that should be isspace((unsigned char)**ts). is* and to*
    > > functions expect a positive integer or EOF, and char may be signed.

    >
    > The value shall be that of an unsigned char and - as usual with C - it
    > doesn't matter where it came from.


    Huh? I think you don't understand the issue. (I also can't figure out
    what you're saying)

    > [...]
    >
    > > line 155 IMHO the parentheses in the expression &(argv[optind])
    > > should be removed, like: trim(&argv[optind])

    >
    > The Right Thing[tm] would be to do away with all of the decoration and
    > write argv + optind when argv + optind is meant.


    I think &argv[optind] and argv + optind both are acceptable.
    &(argv[optind]), however, is not.

    > > line 353 you have several memory leaks after this line, since you
    > > do not free the return value of strdup on error.

    >
    > Since programming initially running as this process is supposed to go
    > away 'soon' (it's only purpose is to start another program), there is
    > no point in returning memory to the malloc heap.


    You're wrong. IEEE 1003.1, 2004 doesn't guarantee that upon exit of
    the program the memory will be freed.

    > > line 395,395 can be replaced with a simple free(exectemp); free(NULL)
    > > is defined to do nothing.

    >
    > Then why call it?


    You clearly haven't EVEN seen the damn code - why are you commenting?
    The context is:

    char *p = NULL;
    /* ... */
    if(something) {
    p = malloc(N);
    /* ... */
    }
    /* ... */
    if(p != NULL)
    free(p);

    > > line 473,478 getpid returns a pid_t, which might not be int (it's
    > > allowed to be any signed integer type). Use printf("%ld",
    > > (long)getpid());

    >
    > pid_t is required to be a signed integer type and all actual process
    > IDs are required to be positive.


    Again you failed to understand the underlying issue.
    The issue is that he passes pid_t to printf's conversion specifier
    'd'. d expects int. pid_t could be any type. Because of that, he
    invokes undefined behavior.

    > [...]
    >
    > > This is not a complete overview of your code; there might be more
    > > bugs.

    >
    > Instead of only "but that's not the way I would have done it", there
    > could additionally be bugs.


    Nonsense. If you don't know C or UNIX properly to understand what I'm
    talking about, it's not my fault.

  15. Re: dh, the daemon helper

    vippstar@gmail.com writes:

    > On Nov 1, 7:11 pm, Rainer Weikusat wrote:
    >> Since programming initially running as this process is supposed to go
    >> away 'soon' (it's only purpose is to start another program), there is
    >> no point in returning memory to the malloc heap.

    >
    > You're wrong. IEEE 1003.1, 2004 doesn't guarantee that upon exit of
    > the program the memory will be freed.


    That is true, but I'd be inclined to regard that as a defect in the
    standard. The description of _exit() is so explicit about the many
    things it frees and destroys that it is hard to imagine the authors
    intended to require it to do all that, but not do something as basic as
    free the process's memory.

    Alternatively, they may have considered it beyond the scope of the
    standard, since the standard doesn't seem to describe how the system
    shall manage memory. It may be considered an implementation detail. In
    which case, you probably can't be sure based on the standard alone that
    there is any way at all to release memory for the use of other
    processes, not _exit() or free() or kill() or munmap() anything else.

    Nevertheless, every IEEE-1003.1-compliant, or otherwise Unix-like,
    operating system that I have ever encountered does indeed release the
    process's memory when it exits, and this behavior is sufficiently
    well-known and relied upon that any system that did not would be
    regarded as unusable, IMHO. Are you aware of any counterexamples?


  16. Re: dh, the daemon helper

    vippstar@gmail.com writes:
    > On Nov 1, 7:11 pm, Rainer Weikusat wrote:
    >> vipps...@gmail.com writes:
    >>
    >> [...]
    >>
    >> > line 52 I think most C programmers prefer const char [] over char
    >> > const [] (no actual difference)

    >>
    >> The 'actual difference' is that const xyz with xyz being the name of
    >> some type is a special case, while const ordinarily binds to the
    >> closest thing left of it, ie char const * is a pointer to a constant
    >> array of char and char * const is a constant pointer to an array of
    >> char.

    >
    > You're wrong, const char [] and char const [] are exactly the same.


    Since I didn't claim their effect would be different, your statement
    that I wrongly made this claim is wrong. I made a statement about the
    grammar rules involved here, which provide a reason why one could
    want to rather use char const then const char.

    > I did not claim anything about const char * and char * const.
    > The equivalent would be char const * and const char *. (not char *
    > const)


    That was an example of the statement about grammer I made: char const
    * means 'char is supposed to be constant', char * const means '* is
    supposed to be constant, ie, not counting the special case of 'const'
    being the first part of a declaration, const would bind to the next
    thing left to it. Which makes for a uniform way to use
    const-specifiers which can be understood by following an extremly
    simple rule.

    Which is an advantage, at least for people who don't strive for
    byzantine expressions because that impedes understanding.

    >> > line 66,74 that should be isspace((unsigned char)**ts). is* and to*
    >> > functions expect a positive integer or EOF, and char may be signed.

    >>
    >> The value shall be that of an unsigned char and - as usual with C - it
    >> doesn't matter where it came from.

    >
    > Huh? I think you don't understand the issue. (I also can't figure out
    > what you're saying)


    If the value is correct, there is no reason to cast, and if the value
    is not correct, the behaviour is undefined (violation of a
    shall-constraint).

    >> [...]
    >>
    >> > line 155 IMHO the parentheses in the expression &(argv[optind])
    >> > should be removed, like: trim(&argv[optind])

    >>
    >> The Right Thing[tm] would be to do away with all of the decoration and
    >> write argv + optind when argv + optind is meant.

    >
    > I think &argv[optind] and argv + optind both are acceptable.
    > &(argv[optind]), however, is not.


    They are both acceptable to a compiler. Trying to hide fundamental
    charachteristics of C, like the fact that the address of an element at
    a distance X to some other element a pointer points to is pointer + X
    tends to confuse humans.

    >> > line 353 you have several memory leaks after this line, since you
    >> > do not free the return value of strdup on error.

    >>
    >> Since programming initially running as this process is supposed to go
    >> away 'soon' (it's only purpose is to start another program), there is
    >> no point in returning memory to the malloc heap.

    >
    > You're wrong. IEEE 1003.1, 2004 doesn't guarantee that upon exit of
    > the program the memory will be freed.


    I am right, since this is the way UNIX(*) processes work.

    >> > line 395,395 can be replaced with a simple free(exectemp); free(NULL)
    >> > is defined to do nothing.

    >>
    >> Then why call it?

    >
    > You clearly haven't EVEN seen the damn code - why are you commenting?
    > The context is:
    >
    > char *p = NULL;
    > /* ... */
    > if(something) {
    > p = malloc(N);
    > /* ... */
    > }
    > /* ... */
    > if(p != NULL)
    > free(p);


    And the rethorical question 'since free(NULL) is a no-op, why call it?'
    doesn't apply to this free precisely why?

    >> > line 473,478 getpid returns a pid_t, which might not be int (it's
    >> > allowed to be any signed integer type). Use printf("%ld",
    >> > (long)getpid());

    >>
    >> pid_t is required to be a signed integer type and all actual process
    >> IDs are required to be positive.

    >
    > Again you failed to understand the underlying issue.


    I misread your sentence as "it's allowed to be a signed integer type",
    which is why I (superflously) wrote that it would be required to be a
    signed interger type.

    >> > This is not a complete overview of your code; there might be more
    >> > bugs.

    >>
    >> Instead of only "but that's not the way I would have done it", there
    >> could additionally be bugs.

    >
    > Nonsense. If you don't know C or UNIX properly to understand what I'm
    > talking about, it's not my fault.


    It's your fault that you assume that you know 'C and UNIX' well enough
    to assume that everything you don't understand (like all of my text)
    must be wrong.

  17. Re: dh, the daemon helper

    On Nov 2, 11:24 am, Rainer Weikusat wrote:
    > vipps...@gmail.com writes:
    > > On Nov 1, 7:11 pm, Rainer Weikusat wrote:
    > >> vipps...@gmail.com writes:

    >
    > >> [...]

    >
    > >> > line 52 I think most C programmers prefer const char [] over char
    > >> > const [] (no actual difference)

    >
    > >> The 'actual difference' is that const xyz with xyz being the name of
    > >> some type is a special case, while const ordinarily binds to the
    > >> closest thing left of it, ie char const * is a pointer to a constant
    > >> array of char and char * const is a constant pointer to an array of
    > >> char.

    >
    > > You're wrong, const char [] and char const [] are exactly the same.

    >
    > Since I didn't claim their effect would be different, your statement
    > that I wrongly made this claim is wrong. I made a statement about the
    > grammar rules involved here, which provide a reason why one could
    > want to rather use char const then const char.


    I don't understand. I said const char [] and char const [] are the
    same type, which is correct.
    You said char const * and char * const are not the same, which is also
    correct, but I don't see how it's related.

    > > I did not claim anything about const char * and char * const.
    > > The equivalent would be char const * and const char *. (not char *
    > > const)

    >
    > That was an example of the statement about grammer I made: char const
    > * means 'char is supposed to be constant', char * const means '* is
    > supposed to be constant, ie, not counting the special case of 'const'
    > being the first part of a declaration, const would bind to the next
    > thing left to it. Which makes for a uniform way to use
    > const-specifiers which can be understood by following an extremly
    > simple rule.
    >
    > Which is an advantage, at least for people who don't strive for
    > byzantine expressions because that impedes understanding.


    So what you're saying is that one way is easier to read than the
    other? Okay, I don't agree but at least I see your point.
    My reasoning to use const char [] over char const [] is because the
    former is more often encountered in C source.

    > >> > line 66,74 that should be isspace((unsigned char)**ts). is* and to*
    > >> > functions expect a positive integer or EOF, and char may be signed.

    >
    > >> The value shall be that of an unsigned char and - as usual with C - it
    > >> doesn't matter where it came from.

    >
    > > Huh? I think you don't understand the issue. (I also can't figure out
    > > what you're saying)

    >
    > If the value is correct, there is no reason to cast, and if the value
    > is not correct, the behaviour is undefined (violation of a
    > shall-constraint).


    If the value is not correct, with the cast it will be and the behavior
    won't be undefined.
    Here's a simple example

    /* begin */
    #include
    #include
    #include
    #include

    int main(void) {

    char buf[BUFSIZ];
    size_t i, j = 0;

    while(fgets(buf, sizeof buf, stdin) != NULL)
    for(j = strlen(buf), i = 0; i < j; i++)
    putchar(toupper((unsigned char)buf[i]));

    if(j && buf[j-1] != '\n')
    putchar('\n');

    if(ferror(stdin)) {
    perror("fgets");
    return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
    }
    /* end */

    Remove that cast and you got an incorrect program.

    > >> [...]

    >
    > >> > line 155 IMHO the parentheses in the expression &(argv[optind])
    > >> > should be removed, like: trim(&argv[optind])

    >
    > >> The Right Thing[tm] would be to do away with all of the decoration and
    > >> write argv + optind when argv + optind is meant.

    >
    > > I think &argv[optind] and argv + optind both are acceptable.
    > > &(argv[optind]), however, is not.

    >
    > They are both acceptable to a compiler. Trying to hide fundamental
    > charachteristics of C, like the fact that the address of an element at
    > a distance X to some other element a pointer points to is pointer + X
    > tends to confuse humans.


    Both expressions are crystal clear. I honestly don't care for those
    who can't understand any of the expressions.
    The only reason I said &argv[optind] would be better is because
    perhaps the programmer thought the parentheses are needed or actually
    doing something.

    > >> > line 353 you have several memory leaks after this line, since you
    > >> > do not free the return value of strdup on error.

    >
    > >> Since programming initially running as this process is supposed to go
    > >> away 'soon' (it's only purpose is to start another program), there is
    > >> no point in returning memory to the malloc heap.

    >
    > > You're wrong. IEEE 1003.1, 2004 doesn't guarantee that upon exit of
    > > the program the memory will be freed.

    >
    > I am right, since this is the way UNIX(*) processes work.


    No. IEEE-1003.1, 2004 is the UNIX standard. What that standard says,
    is how UNIX behaves.

    > >> > line 395,395 can be replaced with a simple free(exectemp); free(NULL)
    > >> > is defined to do nothing.

    >
    > >> Then why call it?

    >
    > > You clearly haven't EVEN seen the damn code - why are you commenting?
    > > The context is:

    >
    > > char *p = NULL;
    > > /* ... */
    > > if(something) {
    > > p = malloc(N);
    > > /* ... */
    > > }
    > > /* ... */
    > > if(p != NULL)
    > > free(p);

    >
    > And the rethorical question 'since free(NULL) is a no-op, why call it?'
    > doesn't apply to this free precisely why?


    This is all nonsensical to me. Is anyone here able to understand what
    you're saying?
    I certainly can't.

    > >> > This is not a complete overview of your code; there might be more
    > >> > bugs.

    >
    > >> Instead of only "but that's not the way I would have done it", there
    > >> could additionally be bugs.

    >
    > > Nonsense. If you don't know C or UNIX properly to understand what I'm
    > > talking about, it's not my fault.

    >
    > It's your fault that you assume that you know 'C and UNIX' well enough
    > to assume that everything you don't understand (like all of my text)
    > must be wrong.


    You've yet to make an accurate remark on my posts.

  18. Re: dh, the daemon helper

    vippstar@gmail.com writes:
    > On Nov 2, 11:24 am, Rainer Weikusat wrote:
    >> vipps...@gmail.com writes:
    >> > On Nov 1, 7:11 pm, Rainer Weikusat wrote:
    >> >> vipps...@gmail.com writes:

    >>
    >> >> [...]

    >>
    >> >> > line 52 I think most C programmers prefer const char [] over char
    >> >> > const [] (no actual difference)

    >>
    >> >> The 'actual difference' is that const xyz with xyz being the name of
    >> >> some type is a special case, while const ordinarily binds to the
    >> >> closest thing left of it, ie char const * is a pointer to a constant
    >> >> array of char and char * const is a constant pointer to an array of
    >> >> char.

    >>
    >> > You're wrong, const char [] and char const [] are exactly the same.

    >>
    >> Since I didn't claim their effect would be different, your statement
    >> that I wrongly made this claim is wrong. I made a statement about the
    >> grammar rules involved here, which provide a reason why one could
    >> want to rather use char const then const char.

    >
    > I don't understand.


    The reason for this is that you are apparently ignoring what I wrote.

    [...]

    >> > I did not claim anything about const char * and char * const.
    >> > The equivalent would be char const * and const char *. (not char *
    >> > const)

    >>
    >> That was an example of the statement about grammer I made: char const
    >> * means 'char is supposed to be constant', char * const means '* is
    >> supposed to be constant, ie, not counting the special case of 'const'
    >> being the first part of a declaration, const would bind to the next
    >> thing left to it. Which makes for a uniform way to use
    >> const-specifiers which can be understood by following an extremly
    >> simple rule.
    >>
    >> Which is an advantage, at least for people who don't strive for
    >> byzantine expressions because that impedes understanding.

    >
    > So what you're saying is that one way is easier to read than the
    > other?


    No, that's what you are saying.

    [...]

    > My reasoning to use const char [] over char const [] is because the
    > former is more often encountered in C source.


    The statement 'use X, because everyone else uses X' is an (unbacked)
    claim that, provided someone would collect statistics one this, the
    numbers would relate to each other in a certain way. I can think of a
    few arguments which could be made in favor of 'use what everyone else
    uses', but you haven't made any.


    >> >> > line 66,74 that should be isspace((unsigned char)**ts). is* and to*
    >> >> > functions expect a positive integer or EOF, and char may be signed.

    >>
    >> >> The value shall be that of an unsigned char and - as usual with C - it
    >> >> doesn't matter where it came from.

    >>
    >> > Huh? I think you don't understand the issue. (I also can't figure out
    >> > what you're saying)

    >>
    >> If the value is correct, there is no reason to cast, and if the value
    >> is not correct, the behaviour is undefined (violation of a
    >> shall-constraint).

    >
    > If the value is not correct, with the cast it will be and the behavior
    > won't be undefined.
    > Here's a simple example
    >
    > /* begin */
    > #include
    > #include
    > #include
    > #include
    >
    > int main(void) {
    >
    > char buf[BUFSIZ];
    > size_t i, j = 0;
    >
    > while(fgets(buf, sizeof buf, stdin) != NULL)
    > for(j = strlen(buf), i = 0; i < j; i++)
    > putchar(toupper((unsigned char)buf[i]));
    >
    > if(j && buf[j-1] != '\n')
    > putchar('\n');
    >
    > if(ferror(stdin)) {
    > perror("fgets");
    > return EXIT_FAILURE;
    > }
    > return EXIT_SUCCESS;
    > }
    > /* end */
    >
    > Remove that cast and you got an incorrect program.


    Not quite. When removing the cast, certain input(s) could result
    in the program having undefined behaviour.

    >> >> [...]

    >>
    >> >> > line 155 IMHO the parentheses in the expression &(argv[optind])
    >> >> > should be removed, like: trim(&argv[optind])

    >>
    >> >> The Right Thing[tm] would be to do away with all of the decoration and
    >> >> write argv + optind when argv + optind is meant.

    >>
    >> > I think &argv[optind] and argv + optind both are acceptable.
    >> > &(argv[optind]), however, is not.

    >>
    >> They are both acceptable to a compiler. Trying to hide fundamental
    >> charachteristics of C, like the fact that the address of an element at
    >> a distance X to some other element a pointer points to is pointer + X
    >> tends to confuse humans.

    >
    > Both expressions are crystal clear.


    Indeed. a[n] is defined as being identical to *(a + n), hence &a[n] is
    the same as &*(a + n). Put into words: A 'pointer-to-type' value is
    derefenced to yield a value of type 'type', the address of which is
    then taken, resulting in a value of type 'pointer-to-type': & and *
    are inverse operations in this respect. Obvioulsy, it is always
    possible to prepend and alternating sequence of such inversive
    operations with an even-numbered length to any expression (with a
    suitable type) and the 'net-effect' will be none at all, expect
    expressed in an arbtitrarily complicated way.

    >> >> > line 353 you have several memory leaks after this line, since you
    >> >> > do not free the return value of strdup on error.

    >>
    >> >> Since programming initially running as this process is supposed to go
    >> >> away 'soon' (it's only purpose is to start another program), there is
    >> >> no point in returning memory to the malloc heap.

    >>
    >> > You're wrong. IEEE 1003.1, 2004 doesn't guarantee that upon exit of
    >> > the program the memory will be freed.

    >>
    >> I am right, since this is the way UNIX(*) processes work.

    >
    > No. IEEE-1003.1, 2004 is the UNIX standard. What that standard says,
    > is how UNIX behaves.


    You are wrong on this one, too: The standard (or any standard)
    describes how a system must behave in order to be compliant with what
    the standard specifies. Specifically, the only (relevant) requirement
    for 'free' is

    The free() function shall cause the space pointed to by
    ptr made available for further allocation.

    What exactly this means depends on the implementation. Specifically,
    your claim that not calling free in this particular circumstances
    would result in 'a memory leak' is a claim about such implementation
    defined behaviour. So, which implementation(s) were you referring to?

    Apart from this, UNIX(*) is not only an API definition but is usually
    also meant to refer to certain actual operating systems implementing
    some (or all) of this API. These implementation can be studied like
    any other 'thing' which exists in this world, and by doing so,
    empirical knowledge about their behaviour can be gained. Like, that
    calling free usually results in making the memory available to the
    incarnation of the malloc allocator associated with a particular
    process and that 'freeing memory' is therefore pointless except
    insofar there could be some future need for it before the process
    terminates.

    >> >> > line 395,395 can be replaced with a simple free(exectemp); free(NULL)
    >> >> > is defined to do nothing.

    >>
    >> >> Then why call it?

    >>
    >> > You clearly haven't EVEN seen the damn code - why are you commenting?
    >> > The context is:

    >>
    >> > char *p = NULL;
    >> > /* ... */
    >> > if(something) {
    >> > p = malloc(N);
    >> > /* ... */
    >> > }
    >> > /* ... */
    >> > if(p != NULL)
    >> > free(p);

    >>
    >> And the rethorical question 'since free(NULL) is a no-op, why call it?'
    >> doesn't apply to this free precisely why?

    >
    > This is all nonsensical to me.


    I cannot possibly make this even more simple.

    [...]

    > You've yet to make an accurate remark on my posts.


    I would suggest to not read them, except for entertainment.


  19. Re: dh, the daemon helper

    On Nov 2, 3:49 pm, Rainer Weikusat wrote:
    > vipps...@gmail.com writes:
    > > On Nov 2, 11:24 am, Rainer Weikusat wrote:
    > >> vipps...@gmail.com writes:
    > >> > On Nov 1, 7:11 pm, Rainer Weikusat wrote:
    > >> >> vipps...@gmail.com writes:




    > > My reasoning to use const char [] over char const [] is because the
    > > former is more often encountered in C source.

    >
    > The statement 'use X, because everyone else uses X' is an (unbacked)
    > claim that, provided someone would collect statistics one this, the
    > numbers would relate to each other in a certain way. I can think of a
    > few arguments which could be made in favor of 'use what everyone else
    > uses', but you haven't made any.


    When it comes to style, yes, use X because everyone else uses X.
    Don't you think so?
    Also, you still haven't answered to me, what you were talking about.

    > >> >> > line 66,74 that should be isspace((unsigned char)**ts). is* and to*
    > >> >> > functions expect a positive integer or EOF, and char may be signed.

    >
    > >> >> The value shall be that of an unsigned char and - as usual with C - it
    > >> >> doesn't matter where it came from.

    >
    > >> > Huh? I think you don't understand the issue. (I also can't figure out
    > >> > what you're saying)

    >
    > >> If the value is correct, there is no reason to cast, and if the value
    > >> is not correct, the behaviour is undefined (violation of a
    > >> shall-constraint).

    >
    > > If the value is not correct, with the cast it will be and the behavior
    > > won't be undefined.
    > > Here's a simple example

    >
    > > /* begin */
    > > #include
    > > #include
    > > #include
    > > #include

    >
    > > int main(void) {

    >
    > > char buf[BUFSIZ];
    > > size_t i, j = 0;

    >
    > > while(fgets(buf, sizeof buf, stdin) != NULL)
    > > for(j = strlen(buf), i = 0; i < j; i++)
    > > putchar(toupper((unsigned char)buf[i]));

    >
    > > if(j && buf[j-1] != '\n')
    > > putchar('\n');

    >
    > > if(ferror(stdin)) {
    > > perror("fgets");
    > > return EXIT_FAILURE;
    > > }
    > > return EXIT_SUCCESS;
    > > }
    > > /* end */

    >
    > > Remove that cast and you got an incorrect program.

    >
    > Not quite. When removing the cast, certain input(s) could result
    > in the program having undefined behaviour.


    So, the code invokes undefined behavior.
    Wherever 'input' is, since it's dependant from the user, you can
    replace it with any possible value.

    > >> >> [...]

    >
    > >> >> > line 155 IMHO the parentheses in the expression &(argv[optind])
    > >> >> > should be removed, like: trim(&argv[optind])

    >
    > >> >> The Right Thing[tm] would be to do away with all of the decoration and
    > >> >> write argv + optind when argv + optind is meant.

    >
    > >> > I think &argv[optind] and argv + optind both are acceptable.
    > >> > &(argv[optind]), however, is not.

    >
    > >> They are both acceptable to a compiler. Trying to hide fundamental
    > >> charachteristics of C, like the fact that the address of an element at
    > >> a distance X to some other element a pointer points to is pointer + X
    > >> tends to confuse humans.

    >
    > > Both expressions are crystal clear.

    >
    > Indeed. a[n] is defined as being identical to *(a + n), hence &a[n] is
    > the same as &*(a + n). Put into words: A 'pointer-to-type' value is
    > derefenced to yield a value of type 'type', the address of which is
    > then taken, resulting in a value of type 'pointer-to-type': & and *
    > are inverse operations in this respect. Obvioulsy, it is always
    > possible to prepend and alternating sequence of such inversive
    > operations with an even-numbered length to any expression (with a
    > suitable type) and the 'net-effect' will be none at all, expect
    > expressed in an arbtitrarily complicated way.


    blablabla, what's your point?

    > >> >> > line 353 you have several memory leaks after this line, since you
    > >> >> > do not free the return value of strdup on error.

    >
    > >> >> Since programming initially running as this process is supposed to go
    > >> >> away 'soon' (it's only purpose is to start another program), there is
    > >> >> no point in returning memory to the malloc heap.

    >
    > >> > You're wrong. IEEE 1003.1, 2004 doesn't guarantee that upon exit of
    > >> > the program the memory will be freed.

    >
    > >> I am right, since this is the way UNIX(*) processes work.

    >
    > > No. IEEE-1003.1, 2004 is the UNIX standard. What that standard says,
    > > is how UNIX behaves.

    >
    > You are wrong on this one, too: The standard (or any standard)
    > describes how a system must behave in order to be compliant with what
    > the standard specifies. Specifically, the only (relevant) requirement
    > for 'free' is


    Wait, why is free relevant?

    > The free() function shall cause the space pointed to by
    > ptr made available for further allocation.


    No, those are not free's requirements.

    see DESCRIPTION.

    > What exactly this means depends on the implementation.


    No, those are not the standards words, so you lack a point.

    > Specifically,
    > your claim that not calling free in this particular circumstances
    > would result in 'a memory leak' is a claim about such implementation
    > defined behaviour. So, which implementation(s) were you referring to?
    >
    > Apart from this, UNIX(*) is not only an API definition but is usually
    > also meant to refer to certain actual operating systems implementing
    > some (or all) of this API. These implementation can be studied like
    > any other 'thing' which exists in this world, and by doing so,
    > empirical knowledge about their behaviour can be gained. Like, that
    > calling free usually results in making the memory available to the
    > incarnation of the malloc allocator associated with a particular
    > process and that 'freeing memory' is therefore pointless except
    > insofar there could be some future need for it before the process
    > terminates.


    Save me the bull**** information. I don't see you making any points,
    but you originally claimed I'm wrong on many things.

    > >> >> > line 395,395 can be replaced with a simple free(exectemp); free(NULL)
    > >> >> > is defined to do nothing.

    >
    > >> >> Then why call it?

    >
    > >> > You clearly haven't EVEN seen the damn code - why are you commenting?
    > >> > The context is:

    >
    > >> > char *p = NULL;
    > >> > /* ... */
    > >> > if(something) {
    > >> > p = malloc(N);
    > >> > /* ... */
    > >> > }
    > >> > /* ... */
    > >> > if(p != NULL)
    > >> > free(p);

    >
    > >> And the rethorical question 'since free(NULL) is a no-op, why call it?'
    > >> doesn't apply to this free precisely why?

    >
    > > This is all nonsensical to me.

    >
    > I cannot possibly make this even more simple.


    It must be because you don't have a damn point.

    > > You've yet to make an accurate remark on my posts.

    >
    > I would suggest to not read them, except for entertainment.


    They sure entertain me.

  20. Re: dh, the daemon helper

    scott@slp53.sl.home (Scott Lurndal) writes:
    > Rainer Weikusat writes:
    >> ... last but not
    >>least - SIGSEGV is sent by the kernel to a process which attempted an
    >>invalid memory access. The default action usually involves to
    >>terminate the process and create a core dump of it[*].

    > [snip]
    >
    >> [*] This very handy feature is typically disabled by 'current'
    >> Linux-distribution, either to conceal the bugginess of the
    >> software or because nobody wants to (or knows how to) fix it,
    >> anyway.

    >
    > This is done for a very simple reason. A significant majority of
    > the users of such distributions don't really care for core dumps
    > filling their filesystem (and a poorly written daemon could quickly
    > fill a filesystem with fairly useless core files).


    The problem with this approach is that it is not possible to decide
    beforehand when core dumps should rather have been enabled. Generally
    disabling them basically means to voluntarily decide to have no
    interest in ever fixing a problem which would otherwise have caused
    one, including to never help with fixing such a problem.

    This is a 'classic' example of how to remain comfortable in face of
    (suspected) bad news by proactively shooting the mailman, based on the
    assumption that these 'bad news' will never have any practical
    relevance.


+ Reply to Thread
Page 1 of 4 1 2 3 ... LastLast