Re: obex-client: doesn't allways closes socket

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

 



Hi,

On Tue, Jul 20, 2010 at 4:25 PM, Vitja Makarov <vitja.makarov@xxxxxxxxx> wrote:
> 2010/7/20 Vitja Makarov <vitja.makarov@xxxxxxxxx>:
>> 2010/7/20 Luiz Augusto von Dentz <luiz.dentz@xxxxxxxxx>:
>>> Hi,
>>>
>>> On Tue, Jul 20, 2010 at 2:46 PM, Vitja Makarov <vitja.makarov@xxxxxxxxx> wrote:
>>>> 2010/7/20 Luiz Augusto von Dentz <luiz.dentz@xxxxxxxxx>:
>>>>> Hi,
>>>>>
>>>>> On Tue, Jul 20, 2010 at 10:12 AM, Vitja Makarov <vitja.makarov@xxxxxxxxx> wrote:
>>>>>> Hi!
>>>>>>
>>>>>> Recently I've found that obex client doesn't allways close socket, I
>>>>>> was using obexd-0.29...
>>>>>> Even more sometimes it closes same socket twice using
>>>>>> g_io_channel_unref() and close()
>>>>>
>>>>> I guess the real ones are gw_obex_close and close, so both end up
>>>>> closing the same fd.
>>>>>
>>>>>> When it comes to client/session.c:rfcomm_connect() with error,
>>>>>> session->sock is not set and socket is not closed on
>>>>>> session_shutdown()
>>>>>> Don't know why g_io_channel_unref() isn't called for that socket..
>>>>>
>>>>> Yep, there is no much point on storing the fd on session->sock in the
>>>>> other hand the io that bt_io_connect gives is the one causing the
>>>>> problem here, either we release this reference and then we have to set
>>>>> not to close the fd or we just keep the io reference and store it on
>>>>> session so we can actually cancel the connection attempt.
>>>>>
>>>>
>>>> My application does send files using obex-client to all available
>>>> devices, after 4-5 hours obex client can't create sockets anymore  (it
>>>> fails with ENFILE, Too many open files), making obex-client absolutely
>>>> unusable.
>>>>
>>>> As workaround I set session->fd even if error was detected, then
>>>> socket will be properly closed.
>>>> It seems to me that here is memory leak also.
>>>>
>>>> vitja.
>>>>
>>>
>>> Can you check if the patch bellow fix those issues:
>>>
>>> diff --git a/client/session.c b/client/session.c
>>> index 334ade4..d761bfb 100644
>>> --- a/client/session.c
>>> +++ b/client/session.c
>>> @@ -173,8 +173,10 @@ static void session_free(struct session_data *session)
>>>        if (session->obex != NULL)
>>>                gw_obex_close(session->obex);
>>>
>>> -       if (session->sock > 2)
>>> -               close(session->sock);
>>> +       if (session->io != NULL) {
>>> +               g_io_channel_shutdown(session->io, TRUE, NULL);
>>> +               g_io_channel_unref(session->io);
>>> +       }
>>>
>>>        if (session->path)
>>>                session_unregistered(session);
>>> @@ -215,13 +217,17 @@ static void rfcomm_callback(GIOChannel *io,
>>> GError *err, gpointer user_data)
>>>                goto done;
>>>        }
>>>
>>> +       /* do not close when gw_obex is using the fd */
>>> +       g_io_channel_set_close_on_unref(session->io, FALSE);
>>> +       g_io_channel_unref(session->io);
>>> +       session->io = NULL;
>>> +
>>>        fd = g_io_channel_unix_get_fd(io);
>>>
>>>        obex = gw_obex_setup_fd(fd, session->target,
>>>                        session->target_len, NULL, NULL);
>>>
>>> -       callback->session->sock = fd;
>>> -       callback->session->obex = obex;
>>> +       session->obex = obex;
>>>
>>>  done:
>>>        callback->func(callback->session, callback->data);
>>> @@ -231,9 +237,9 @@ done:
>>>        g_free(callback);
>>>  }
>>>
>>> -static int rfcomm_connect(const bdaddr_t *src,
>>> -                               const bdaddr_t *dst, uint8_t channel,
>>> -                                       BtIOConnect function, gpointer user_data)
>>> +static GIOChannel *rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst,
>>> +                                       uint8_t channel, BtIOConnect function,
>>> +                                       gpointer user_data)
>>>  {
>>>        GIOChannel *io;
>>>        GError *err = NULL;
>>> @@ -245,11 +251,11 @@ static int rfcomm_connect(const bdaddr_t *src,
>>>                                BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
>>>                                BT_IO_OPT_INVALID);
>>>        if (io != NULL)
>>> -               return 0;
>>> +               return io;
>>>
>>>        error("%s", err->message);
>>>        g_error_free(err);
>>> -       return -EIO;
>>> +       return NULL;
>>>  }
>>>
>>>  static void search_callback(uint8_t type, uint16_t status,
>>> @@ -309,8 +315,11 @@ static void search_callback(uint8_t type, uint16_t status,
>>>
>>>        callback->session->channel = channel;
>>>
>>> -       if (rfcomm_connect(&callback->session->src, &callback->session->dst,
>>> -                                       channel, rfcomm_callback, callback) == 0) {
>>> +       callback->session->io = rfcomm_connect(&callback->session->src,
>>> +                                               &callback->session->dst,
>>> +                                               channel, rfcomm_callback,
>>> +                                               callback);
>>> +       if (callback->session->io != NULL) {
>>>                sdp_close(callback->sdp);
>>>                return;
>>>        }
>>> @@ -418,7 +427,6 @@ struct session_data *session_create(const char *source,
>>>                return NULL;
>>>
>>>        session->refcount = 1;
>>> -       session->sock = -1;
>>>        session->channel = channel;
>>>
>>>        session->conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
>>> @@ -465,8 +473,11 @@ struct session_data *session_create(const char *source,
>>>        callback->data = user_data;
>>>
>>>        if (session->channel > 0) {
>>> -               err = rfcomm_connect(&session->src, &session->dst,
>>> -                               session->channel, rfcomm_callback, callback);
>>> +               session->io = rfcomm_connect(&session->src, &session->dst,
>>> +                                                       session->channel,
>>> +                                                       rfcomm_callback,
>>> +                                                       callback);
>>> +               err = (session->io == NULL) ? -EINVAL : 0;
>>>        } else {
>>>                callback->sdp = service_connect(&session->src, &session->dst,
>>>                                                service_callback, callback);
>>> diff --git a/client/session.h b/client/session.h
>>> index 73337cd..9451c25 100644
>>> --- a/client/session.h
>>> +++ b/client/session.h
>>> @@ -40,10 +40,10 @@ struct session_data {
>>>        int target_len;
>>>        uuid_t uuid;            /* Bluetooth Service Class */
>>>        gchar *path;            /* Session path */
>>> -       int sock;
>>>        DBusConnection *conn;
>>>        DBusMessage *msg;
>>>        GwObex *obex;
>>> +       GIOChannel *io;
>>>        struct agent_data *agent;
>>>        struct session_callback *callback;
>>>        gchar *owner;           /* Session owner */
>>>
>>>
>>>
>>> --
>>> Luiz Augusto von Dentz
>>> Computer Engineer
>>>
>>
>> This seems to work, thanks
>>
>
> One more question can some socket errors (GError) be forwarded to
> dbus, so on client side I can get connection refused and so on,
> messages?
>
> That should be better than empty  "dbus.exceptions.DBusException:
> org.openobex.Error.Failed:" message

Sure, that could be done, but lets fix one issue at time. Does the
previous patch fixed your problem?


-- 
Luiz Augusto von Dentz
Computer Engineer
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux