Re: [gmime-devel] GObject unref hell



On 06/11/13 13:31, Jeffrey Stedfast wrote:
On 11/6/2013 4:21 AM, Mario Theodoridis wrote:
>> ....
2. Is there a way to safely unref a GObject, i.e. unref it if it needs
to be? This is mainly because it is not always clear to me when and
when not due to issues like the current.

No, but as a general set of rules:

1. if you create a new object and set it as a child on another object,
you need to unref it
2. when you get an object from another object, you don't - think if it
as returning a const pointer.

example of rule #1:

child = g_mime_child_new ();
g_mime_parent_add_child (parent, child);
g_object_unref (child);

The reason you unref here is because the parent adds a ref to the child
when you add it.

Essentially you own a ref to child, and, once you've added the child to
the parent, the parent *also* owns a ref to the child. Thus there are 2
references to it, but if you are done with the child, you need to unref
it (or you leak a reference to it).

example of rule #2:

child = g_mime_parent_get_child (parent);
// no need to unref child because the parent does not ref the child when
it returns it

// to extend this example further...
g_mime_parent_add_child (parent2, child);
// still don't unref the child because you never ref'd it

In this example, when you get the child from the parent, only the parent
owns a reference to the child. When you add it to parent2, parent2 adds
another reference, which means that now both parent objects own a ref to
the child, but since you still don't own a reference to the child, you
don't unref it.

Yes , this is how i understood it, too.
But i'm still getting these weired errors.
Lookin at the error log, i have a feeling it happens in
> g_mime_message_set_mime_part (message, (GMimeObject*) multipart);
when the old mime_part gets unrefed.

Here's the complete function with error checking removed for brevity.
It rewrites an existing message to reflect its new structure.

msg->message is of type GMimeMessage * and
msg->headerList of GMimeHeaderList *


int mimeFromRgsMsg(msgObj msg, rgsMsg rgMsg) {
    uint attCnt = 0;
    GMimeDataWrapper *content = NULL;
    GMimeStream *mem = NULL;
    GMimePart *part = NULL;
    GMimeMultipart *multipart = NULL;
    char *res = NULL;
    size_t resLen = 0;
    rgsAtt att = NULL;
    char *fileName = NULL;
    char *type = NULL, *subtype = NULL, *param = NULL, *value = NULL;
    GMimeHeaderList *oldHeaderList = NULL;
    GMimeHeaderIter *iter = NULL;

    do {

        /* make the main body first */

        /* get the body */
        rgsGet(rgMsg, RGS_BODY, &res);

        /* find type */
        getType(msg, res, strlen(res), &type, &subtype, &param, &value);

        mem = g_mime_stream_mem_new_with_buffer (res, strlen (res));
        content = g_mime_data_wrapper_new_with_stream ((GMimeStream *) mem,

GMIME_CONTENT_ENCODING_DEFAULT);
        rfunref (mem);

        part = g_mime_part_new_with_type (type, subtype);
        g_mime_object_set_content_type_parameter ((GMimeObject *) part,
                                                  param, value);
        if (g_ascii_strcasecmp(type, "text") == 0) {
            g_mime_part_set_content_encoding(
                    part, GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE);
        } else {
            g_mime_part_set_content_encoding (
                    part, GMIME_CONTENT_ENCODING_BASE64);
        }
        g_mime_part_set_content_object (part, content);
        rfunref (content);

        /* get a list of the old headers so we can delete what's no longer
         * needed */
oldHeaderList = g_mime_object_get_header_list(msg->message->mime_part);
        iter = g_mime_header_iter_new();
        if(g_mime_header_list_get_iter(oldHeaderList, iter)) {
            msg->oldHeaders = g_array_new(FALSE, FALSE, sizeof (char*));
            do {
char* name = g_strdup((char*)g_mime_header_iter_get_name(iter));
                g_array_append_val(msg->oldHeaders, name);
            } while(g_mime_header_iter_next (iter));
        }
        if (iter) g_mime_header_iter_free(iter);
        iter = NULL;

        /* yank the body and rgf attachment */
        if (GMIME_IS_MULTIPART (msg->message->mime_part)) {
g_mime_multipart_clear((GMimeMultipart *)msg->message->mime_part);
        }

        rgsGetAttachmentCount(rgMsg, &attCnt);

        if (attCnt == 0) {
            /* remove unneeded multi part */
g_mime_message_set_mime_part (msg->message, (GMimeObject*) part); msg->headerList = g_mime_object_get_header_list((GMimeObject*)part);
            rfunref (part);
            break;
        }

        /* there are many parts */
        multipart = g_mime_multipart_new_with_subtype ("mixed");
        g_mime_multipart_add (multipart, (GMimeObject *) part);
        rfunref (part);
        part = NULL;

        do {
            rgsGetAttachment(rgMsg, &att);
            if (!att) break; /* we're done */

            rgsAttGetName(att, &fileName);

            /* get attachment data */
            rgsAttGetData(att, (void**) &res, &resLen);

            mem = g_mime_stream_mem_new_with_buffer (res, resLen);
            content = g_mime_data_wrapper_new_with_stream (
                        (GMimeStream*)mem, GMIME_CONTENT_ENCODING_DEFAULT);
            rfunref (mem);

            /* find type */
            getType(msg, res, resLen, &type, &subtype, &param, &value);

            part = g_mime_part_new_with_type(type, subtype);
            g_mime_part_set_filename(part, fileName);
            g_mime_object_set_content_type_parameter((GMimeObject*)part,
                                                     param, value);
            if (g_ascii_strcasecmp(type, "text") == 0) {
                g_mime_part_set_content_encoding(
                        part, GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE);
            } else {
                g_mime_part_set_content_encoding (
                        part, GMIME_CONTENT_ENCODING_BASE64);
            }
            g_mime_part_set_content_object (part, content);
            rfunref (content);

            g_mime_multipart_add (multipart, (GMimeObject *) part);
            rfunref (part);

        } while(TRUE);

g_mime_message_set_mime_part (msg->message, (GMimeObject*) multipart); msg->headerList = g_mime_object_get_header_list((GMimeObject*)multipart);
        rfunref (multipart);

    } while(FALSE);

    rfunref (mem);
    rfunref (content);
    rfunref (part);
    rfunref (multipart);

    return 0;
}



--
Mit Freundlichen Grüßen / Regards

Mario Theodoridis

regify®
your mail matters


regify S.A. | 2b, Ennert dem Bierg | L-5244 Sandweiler / Luxembourg

phone: +352 268 9321 | internet: www.regify.com
executive board: Kurt Kammerer, Volker Schmid
supervisory board chairman: Dr. Hans-Peter Kohlhammer
commercial register: Registre de Commerce et des Sociétés B 156705


regify GmbH | Römerstrasse 39 | D-78183 Hüfingen / Germany

Telefon: +49 771 8978 4238 | Internet: www.regify.com
Geschäftsführung: Kurt Kammerer, Volker Schmid
Handelsregister: Amtsgericht Freiburg HRB 709343


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]