Changeset 6f7cd5d in mainline for uspace/srv/hid/remcons/remcons.c


Ignore:
Timestamp:
2012-01-09T18:05:37Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
3806317
Parents:
5576358
Message:

remcons: safer wrt. fibrils

File:
1 edited

Legend:

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

    r5576358 r6f7cd5d  
    7474        size_t socket_buffer_len;
    7575        size_t socket_buffer_pos;
     76
     77        /* Destruction CV with guard. */
     78        int refcount;
     79        fibril_condvar_t refcount_cv;
     80        fibril_mutex_t refcount_mutex;
    7681} client_t;
    7782
     
    103108        client->socket_buffer_pos = 0;
    104109
     110        fibril_condvar_initialize(&client->refcount_cv);
     111        fibril_mutex_initialize(&client->refcount_mutex);
     112        client->refcount = 0;
     113
    105114
    106115        fibril_mutex_lock(&clients_guard);
     
    154163}
    155164
    156 static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    157 {
    158         /* Find the client. */
    159         client_t *client = client_find(IPC_GET_ARG1(*icall));
    160         if (client == NULL) {
    161                 async_answer_0(iid, ENOENT);
    162                 return;
    163         }
    164 
    165         printf("New client for service %s.\n", client->service_name);
    166 
    167         /* Accept the connection */
    168         async_answer_0(iid, EOK);
    169 
    170         /*
    171          * Force character mode.
    172          * IAC WILL ECHO IAC WILL SUPPRESS_GO_AHEAD IAC WONT LINEMODE
    173          * http://stackoverflow.com/questions/273261/force-telnet-client-into-character-mode
    174          */
    175         const char force_char_mode[] = {255, 251, 1, 255, 251, 3, 255, 252, 34};
    176         send(client->socket, (void *)force_char_mode, sizeof(force_char_mode), 0);
    177 
     165static void client_connection_message_loop(client_t *client)
     166{
    178167        while (true) {
    179168                ipc_call_t call;
     
    302291}
    303292
     293static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     294{
     295        /* Find the client. */
     296        client_t *client = client_find(IPC_GET_ARG1(*icall));
     297        if (client == NULL) {
     298                async_answer_0(iid, ENOENT);
     299                return;
     300        }
     301
     302        printf("New client for service %s.\n", client->service_name);
     303
     304        /* Accept the connection, increment reference. */
     305        async_answer_0(iid, EOK);
     306        fibril_mutex_lock(&client->refcount_mutex);
     307        client->refcount++;
     308        fibril_mutex_unlock(&client->refcount_mutex);
     309
     310        /*
     311         * Force character mode.
     312         * IAC WILL ECHO IAC WILL SUPPRESS_GO_AHEAD IAC WONT LINEMODE
     313         * http://stackoverflow.com/questions/273261/force-telnet-client-into-character-mode
     314         */
     315        const char force_char_mode[] = {255, 251, 1, 255, 251, 3, 255, 252, 34};
     316        send(client->socket, (void *)force_char_mode, sizeof(force_char_mode), 0);
     317
     318        client_connection_message_loop(client);
     319
     320        /* Announce client disconnection. */
     321        fibril_mutex_lock(&client->refcount_mutex);
     322        client->refcount--;
     323        fibril_condvar_signal(&client->refcount_cv);
     324        fibril_mutex_unlock(&client->refcount_mutex);
     325}
     326
    304327
    305328static int network_client_fibril(void *arg)
     
    327350                return EOK;
    328351        }
     352        fibril_mutex_lock(&client->refcount_mutex);
     353        client->refcount++;
     354        fibril_mutex_unlock(&client->refcount_mutex);
    329355
    330356        task_exit_t task_exit;
     
    334360
    335361        closesocket(client->socket);
     362        rc = loc_service_unregister(client->service_id);
     363        if (rc != EOK) {
     364                fprintf(stderr, "Warning: failed to unregister %s: %s\n", client->service_name, str_error(rc));
     365        }
     366
     367        /* Wait for all clients to exit. */
     368        fibril_mutex_lock(&client->refcount_mutex);
     369        /* Drop our reference. */
     370        client->refcount--;
     371        while (client->refcount > 0) {
     372                fibril_condvar_wait(&client->refcount_cv, &client->refcount_mutex);
     373        }
     374        fibril_mutex_unlock(&client->refcount_mutex);
    336375
    337376        client_destroy(client);
Note: See TracChangeset for help on using the changeset viewer.