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

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

 



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
--
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