[ltt-dev] [UST PATCH] remove duplicate return

Mathieu Desnoyers compudj at krystal.dyndns.org
Wed Sep 8 12:40:30 EDT 2010


* David Goulet (david.goulet at polymtl.ca) wrote:
> Following this thread.
>
> Should these be negative value ? (in include/ust/ustcmd.h)
>
> #define USTCMD_ERR_CONN		1 /* Process connection error */
> #define USTCMD_ERR_ARG		2 /* Invalid function argument */
> #define USTCMD_ERR_GEN		3 /* General ustcmd error */

Yes. And the caller of ustcmd_set_marker_state should deal with the
return value.

Thanks,

Mathieu

>
> David
>
> On 10-09-07 11:43 AM, Mathieu Desnoyers wrote:
>> * Pierre-Marc Fournier (pierre-marc.fournier at polymtl.ca) wrote:
>>> On 09/06/2010 11:29 AM, Mathieu Desnoyers wrote:
>>>> * Mathieu Desnoyers (compudj at krystal.dyndns.org) wrote:
>>>>> * Pierre-Marc Fournier (pierre-marc.fournier at polymtl.ca) wrote:
>>>>>> I disagree with you Mathieu. These retvals are the same as i/o
>>>>>> syscalls (read/write/send/recv/...)and therefore should in my opinion
>>>>>> remain as is.
>>>>>
>>>>> Well, this function is not technically the same as i/o syscalls at all.
>>>>> It uses I/O syscalls, but it is not an I/O syscall per se, so the return
>>>>> value transformation to a more standard pattern (neg err val, 0 ok)
>>>>> should happen right in this function rather than to let all callers
>>>>> handle this. I/O syscalls use positive return values to indicate the
>>>>> number of bytes read/written/etc. Here, this function arbitrarily choose
>>>>> 1 to indicate that "something has been sent" without caring about the
>>>>> amount of data moved at all.
>>>>>
>>>>> So as it doesn't need the whole positive range to spell out the amount
>>>>> of data moved, it doesn't need to do the same special-cases that the I/O
>>>>> syscalls are doing. It adds a lot of error values management oddness
>>>>> without adding anything.
>>>>>
>>>>> So even though I agree with you that this function is close to the I/O
>>>>> system calls because it calls it, it is very far from the I/O syscalls
>>>>> semantically (we don't care about the number of bytes written), and even
>>>>> though we might be tempted to use the same error values as system calls
>>>>> for them, the fact that we just don't care about the number of bytes
>>>>> written combined with the fact that standardizing error value across the
>>>>> code makes it much easier to follow and to write just call for this
>>>>> change.
>>>>
>>>> By the way, looking at include/share.h:patient_write(), in the case
>>>> where write returns 0, I think we should consider this as a success and
>>>> loop again to retry write rather than consider that an error occurred.
>>>> The same apply to patient_send(). See the manpages for details:
>>>>
>>>> write(2):
>>>>
>>>> RETURN VALUE
>>>>          On  success,  the  number  of bytes written is returned (zero indicates
>>>>          nothing was written).  On error, -1  is  returned,  and  errno  is  set
>>>>          appropriately.
>>>>
>>>>          If  count  is  zero  and  fd refers to a regular file, then write() may
>>>>          return a failure status if one of the errors below is detected.  If  no
>>>>          errors  are  detected,  0  will  be  returned without causing any other
>>>>          effect.  If count is zero and fd refers to a file other than a  regular
>>>>          file, the results are not specified.
>>>>
>>>> send(2):
>>>> RETURN VALUE
>>>>          On success, these calls return  the  number  of  characters sent.   On
>>>>          error, -1 is returned, and errno is set appropriately.
>>>>
>>>
>>> No. 0 indicates end of stream
>>
>> By end of stream, you mean this sequence ?
>>
>> server:
>>    (block SIGPIPE)
>>    sockwrite = socket(AF_UNIX, SOCK_STREAM, 0);
>>    addr.sun_family = AF_UNIX;
>>    strcpy(addr.sun_path, "./mysocket");
>>
>>    /* wait for client to create the unix socket */
>>    sleep(2);
>>
>>    connect(sockwrite, (struct sockaddr *)&addr, sizeof(addr));)
>>
>>    /* let's do one write which will be consumed by the client */
>>    write(sockwrite, "blah", sizeof("blah"));
>>
>>    /* wait for client to close FD */
>>    sleep(2);
>>
>>    ret = write(sockwrite, "blah", sizeof("blah"));
>>    ( or even with ret = send(sockwrite, "blah", sizeof("blah"), MSG_NOSIGNAL); )
>>    printf("write ret %ld errno %ld\n", ret, errno);
>>
>>
>> client:
>>    (block SIGPIPE)
>>    sockserv = socket(AF_UNIX, SOCK_STREAM, 0);
>>    addr.sun_family = AF_UNIX;
>>    strcpy(addr.sun_path, "./mysocket");
>>    bind(sockserv, (struct sockaddr *)&addr, sizeof(addr));
>>    listen(sockserv, 1);
>>    sockread = accept(sockserv, NULL, NULL);
>>
>>    recv(sockread, buf, sizeof(buf), 0);
>>
>>    close(sockread);
>>
>> The server printf returns:
>>
>>   "write ret -1 errno 32"
>>
>> So the return value is -1, with an error number: EPIPE: Broken pipe
>>
>>> and looping on it will result in an
>>> infinite loop. You need to refer to the specific backend driver to
>>> understand these specific semantics. The read/write manpages are
>>> notorious for their non-clarity about this.
>>
>> This is what I just did by creating my small test program. Unless I am
>> misunderstanding your definition of "end of stream", your assumptions
>> about the way the unix sockets work seem incorrect.
>>
>> Note that as the manpage says, if the file descriptor refers to a
>> regular file, then write() can return 0, with an error number set, which
>> could indicate that an error occured. If the file descriptor refers to a
>> file other than a regular file, the results are unspecified. So I think
>> the sane way to handle this would be to check if errno is 0 when write
>> returns 0. If errno != 0, then we have an error, but if errno == 0, I'd
>> consider that 0 bytes were written and retry.
>>
>>
>> By the way, you forgot to reply to my first message above which covers
>> the topic of semantics, so I'm re-pasting it here.
>>
>> (about ustcomm_send_request())
>>
>> Well, this function is not technically the same as i/o syscalls at all.
>> It uses I/O syscalls, but it is not an I/O syscall per se, so the return
>> value transformation to a more standard pattern (neg err val, 0 ok)
>> should happen right in this function rather than to let all callers
>> handle this. I/O syscalls use positive return values to indicate the
>> number of bytes read/written/etc. Here, this function arbitrarily choose
>> 1 to indicate that "something has been sent" without caring about the
>> amount of data moved at all.
>>
>> So as it doesn't need the whole positive range to spell out the amount
>> of data moved, it doesn't need to do the same special-cases that the I/O
>> syscalls are doing. It adds a lot of error values management oddness
>> without adding anything.
>>
>> So even though I agree with you that this function is close to the I/O
>> system calls because it calls it, it is very far from the I/O syscalls
>> semantically (we don't care about the number of bytes written), and even
>> though we might be tempted to use the same error values as system calls
>> for them, the fact that we just don't care about the number of bytes
>> written combined with the fact that standardizing error value across the
>> code makes it much easier to follow and to write just call for this
>> change.
>>
>>
>> Thanks,
>>
>> Mathieu
>>
>>>
>>> pmf
>>>
>>
>
> -- 
> David Goulet
> LTTng project, DORSAL Lab.
>
> PGP/GPG : 1024D/16BD8563
> BE3C 672B 9331 9796 291A  14C6 4AF7 C14B 16BD 8563
>

-- 
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com




More information about the lttng-dev mailing list