Changeset 1870d81 in mainline


Ignore:
Timestamp:
2012-01-11T16:25:44Z (12 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
787b65b
Parents:
7c2bb2c
Message:

remcons: kill task on socket close

Timeout variants are needed otherwise we might get blocked.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hid/remcons/remcons.c

    r7c2bb2c r1870d81  
    7676        size_t socket_buffer_pos;
    7777
    78         /* Destruction CV with guard. */
    79         int refcount;
     78        task_id_t task_id;
     79
     80        /* Reference counting. */
    8081        fibril_condvar_t refcount_cv;
    8182        fibril_mutex_t refcount_mutex;
     83        bool task_finished;
     84        int locsrv_connection_count;
     85        bool socket_closed;
    8286} client_t;
    8387
     
    125129        fibril_condvar_initialize(&client->refcount_cv);
    126130        fibril_mutex_initialize(&client->refcount_mutex);
    127         client->refcount = 0;
     131        client->task_finished = false;
     132        client->socket_closed = false;
     133        client->locsrv_connection_count = 0;
    128134
    129135
     
    146152}
    147153
    148 static client_t *client_find(service_id_t id)
     154static client_t *client_get_for_client_connection(service_id_t id)
    149155{
    150156        client_t *client = NULL;
     
    158164                }
    159165        }
     166        if (client == NULL) {
     167                fibril_mutex_unlock(&clients_guard);
     168                return NULL;
     169        }
     170
     171        client_t *tmp = client;
     172        fibril_mutex_lock(&tmp->refcount_mutex);
     173        client->locsrv_connection_count++;
     174
     175        /*
     176         * Refuse to return client whose task already finished or when
     177         * the socket is already closed().
     178         */
     179        if (client->task_finished || client->socket_closed) {
     180                client = NULL;
     181                client->locsrv_connection_count--;
     182        }
     183
     184        fibril_mutex_unlock(&tmp->refcount_mutex);
     185
     186
    160187        fibril_mutex_unlock(&clients_guard);
    161188
     
    182209        while (true) {
    183210                ipc_call_t call;
    184                 ipc_callid_t callid = async_get_call(&call);
     211                ipc_callid_t callid = 0;
     212                while (callid == 0) {
     213                        callid = async_get_call_timeout(&call, 1000);
     214
     215                        fibril_mutex_lock(&client->refcount_mutex);
     216                        bool bail_out = client->socket_closed || client->task_finished;
     217                        fibril_mutex_unlock(&client->refcount_mutex);
     218
     219                        if (bail_out) {
     220                                if (callid != 0) {
     221                                        async_answer_0(callid, EINTR);
     222                                }
     223                                return;
     224                        }
     225                }
    185226               
    186227                if (!IPC_GET_IMETHOD(call)) {
     
    201242                                if (client->socket_buffer_len <= client->socket_buffer_pos) {
    202243                                        int recv_length = recv(client->socket, client->socket_buffer, BUFFER_SIZE, 0);
    203                                         if (recv_length == 0) {
     244                                        if ((recv_length == 0) || (recv_length == ENOTCONN)) {
     245                                                fibril_mutex_lock(&client->refcount_mutex);
     246                                                client->socket_closed = true;
     247                                                fibril_mutex_unlock(&client->refcount_mutex);
    204248                                                async_answer_0(callid, ENOENT);
    205249                                                return;
     
    207251                                        if (recv_length < 0) {
    208252                                                async_answer_0(callid, EINVAL);
    209                                                 break;
     253                                                return;
    210254                                        }
    211255                                        client->socket_buffer_len = recv_length;
     
    309353{
    310354        /* Find the client. */
    311         client_t *client = client_find(IPC_GET_ARG1(*icall));
     355        client_t *client = client_get_for_client_connection(IPC_GET_ARG1(*icall));
    312356        if (client == NULL) {
    313357                async_answer_0(iid, ENOENT);
     
    319363        /* Accept the connection, increment reference. */
    320364        async_answer_0(iid, EOK);
    321         fibril_mutex_lock(&client->refcount_mutex);
    322         client->refcount++;
    323         fibril_mutex_unlock(&client->refcount_mutex);
    324365
    325366        /* Force character mode. */
     
    331372        /* Announce client disconnection. */
    332373        fibril_mutex_lock(&client->refcount_mutex);
    333         client->refcount--;
     374        client->locsrv_connection_count--;
    334375        fibril_condvar_signal(&client->refcount_cv);
    335376        fibril_mutex_unlock(&client->refcount_mutex);
     
    350391                    APP_GETTERM, term, "/app/bdsh", str_error(rc));
    351392                fibril_mutex_lock(&client->refcount_mutex);
    352                 client->refcount--;
     393                client->task_finished = true;
    353394                fibril_condvar_signal(&client->refcount_cv);
    354395                fibril_mutex_unlock(&client->refcount_mutex);
    355396                return EOK;
    356397        }
     398
     399        fibril_mutex_lock(&client->refcount_mutex);
     400        client->task_id = task;
     401        fibril_mutex_unlock(&client->refcount_mutex);
    357402
    358403        task_exit_t task_exit;
     
    363408        /* Announce destruction. */
    364409        fibril_mutex_lock(&client->refcount_mutex);
    365         client->refcount--;
     410        client->task_finished = true;
    366411        fibril_condvar_signal(&client->refcount_cv);
    367412        fibril_mutex_unlock(&client->refcount_mutex);
     
    370415}
    371416
     417static bool client_can_be_destroyed_no_lock(client_t *client)
     418{
     419        return client->task_finished && client->socket_closed &&
     420            (client->locsrv_connection_count == 0);
     421}
    372422
    373423static int network_client_fibril(void *arg)
     
    385435            client->service_id);
    386436
    387         fibril_mutex_lock(&client->refcount_mutex);
    388         client->refcount++;
    389         fibril_mutex_unlock(&client->refcount_mutex);
    390 
    391437        fid_t spawn_fibril = fibril_create(spawn_task_fibril, client);
    392438        assert(spawn_fibril);
     
    395441        /* Wait for all clients to exit. */
    396442        fibril_mutex_lock(&client->refcount_mutex);
    397         while (client->refcount > 0) {
    398                 fibril_condvar_wait(&client->refcount_cv, &client->refcount_mutex);
     443        while (!client_can_be_destroyed_no_lock(client)) {
     444                if (client->task_finished) {
     445                        closesocket(client->socket);
     446                        client->socket_closed = true;
     447                        continue;
     448                } else if (client->socket_closed) {
     449                        if (client->task_id != 0) {
     450                                task_kill(client->task_id);
     451                        }
     452                }
     453                fibril_condvar_wait_timeout(&client->refcount_cv, &client->refcount_mutex, 1000);
    399454        }
    400455        fibril_mutex_unlock(&client->refcount_mutex);
    401456
    402         closesocket(client->socket);
    403457        rc = loc_service_unregister(client->service_id);
    404458        if (rc != EOK) {
Note: See TracChangeset for help on using the changeset viewer.