[Spice-devel] [phodav PATCH 3/3 v7 spice-webdavd-windows: Dismount shared folder on service stop

Victor Toso lists at victortoso.com
Thu May 26 11:08:58 UTC 2016


Hi,

On Wed, May 25, 2016 at 03:51:44PM +0200, Lukáš Venhoda wrote:
> From: Lukas Venhoda <lvenhoda at redhat.com>
>
> When stopping the service, automatically disconnect shared folder on
> windows. Not dismounting could lead to multiple shared folders.
> ---
> Changes since v6:
>  - Changed gchar* to ServiceData*
>  - Added mutex for ServiceData multithread handeling
>  - Moved ServiceData from windows service only to all OS
>     - ServiceData is currently empty on Linux
>     - Can be used in the future
>  - Added correct unmapping for --no-service

Great.

>
> Changes since v5:
>  - fixed indentation
>  - fixed * indentaion
>  - removed return from void functions
>  - changed ServiceData * to gpointer, so that it compiles on linux
>
> Changes since v4:
>  - Dont lookup drive letter when unmapping
>     - Uses a service_data structure and map_drive_data structure to store
>       the drive_letter for later use while unmapping
>  - Better debug messages
>
> Changes since v3:
>  - Better handeling of string names
>  - Syntax cleanup
>  - Remove global variable drive_letter
>     - Now scans for mapped drive and unmaps it
> 
> Changes since v2:
>  - None
> 
> Changes since v1:
>  - New patch
> ---
>  spice/spice-webdavd.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 60 insertions(+), 4 deletions(-)
> 
> diff --git a/spice/spice-webdavd.c b/spice/spice-webdavd.c
> index 216d895..0e1081e 100644
> --- a/spice/spice-webdavd.c
> +++ b/spice/spice-webdavd.c
> @@ -57,6 +57,14 @@ typedef struct _OutputQueueElem
>    gpointer      user_data;
>  } OutputQueueElem;
> 
> +typedef struct _ServiceData
> +{
> +#ifdef G_OS_WIN32
> +  gchar drive_letter;
> +  GMutex mutex;
> +#endif
> +} ServiceData;
> +

Documentation states: "If a GMutex is placed in other contexts (eg:
embedded in a struct) then it must be explicitly initialised using
g_mutex_init()." I think you are missing g_mutex_init() and
g_mutex_clear()

>  static GCancellable *cancel;
> 
>  static OutputQueue*
> @@ -749,6 +757,7 @@ typedef enum _MapDriveEnum
> 
>  typedef struct _MapDriveData
>  {
> +  ServiceData *service_data;
>    GCancellable *cancel_map;
>  } MapDriveData;
> 
> @@ -855,6 +864,31 @@ map_drive(const gchar drive_letter)
>  }
> 
>  static void
> +unmap_drive(const gchar drive_letter)
> +{
> +  gchar local_name[MAX_DRIVE_LETTER_SIZE];
> +  guint32 errn;
> +
> +  g_snprintf(local_name, MAX_DRIVE_LETTER_SIZE, "%c:", drive_letter);
> +  errn = WNetCancelConnection2(local_name, CONNECT_UPDATE_PROFILE, TRUE);
> +
> +  if (errn == NO_ERROR)
> +    {
> +      g_debug ("Shared folder unmapped succesfully");
> +    }
> +  else if (errn == ERROR_NOT_CONNECTED)
> +    {
> +      g_debug ("Drive %c is not connected", drive_letter);
> +    }
> +  else
> +    {
> +      g_warning ("map_drive error %d", errn);
> +    }
> +
> +  return;
> +}
> +
> +static void
>  map_drive_cb(GTask *task,
>               gpointer source_object,
>               gpointer task_data,
> @@ -896,11 +930,16 @@ map_drive_cb(GTask *task,
>        //TODO: After mapping, rename network drive from \\localhost at PORT\DavWWWRoot
>        //      to something like SPICE Shared Folder
>      }
> +
> +  g_mutex_lock(&map_drive_data->service_data->mutex);
> +  map_drive_data->service_data->drive_letter = drive_letter;
> +  g_mutex_unlock(&map_drive_data->service_data->mutex);
>  }
> +
>  #endif
> 
>  static void
> -run_service (void)
> +run_service (ServiceData *service_data)
>  {
>    g_debug ("Run service");
> 
> @@ -909,6 +948,11 @@ run_service (void)
>    map_drive_data.cancel_map = g_cancellable_new ();
>    gchar drive_letter = get_spice_folder_letter ();
> 
> +  g_mutex_lock(&service_data->mutex);
> +  service_data->drive_letter = drive_letter;
> +  map_drive_data.service_data = service_data;
> +  g_mutex_unlock(&service_data->mutex);
> +
>    if (drive_letter == 0)
>      {
>        GTask *map_drive_task = g_task_new (NULL, NULL, NULL, NULL);
> @@ -990,10 +1034,15 @@ service_ctrl_handler (DWORD ctrl, DWORD type, LPVOID data, LPVOID ctx)
>  {
>    DWORD ret = NO_ERROR;
> 
> +  ServiceData *service_data = ctx;
> +
>    switch (ctrl)
>      {
>      case SERVICE_CONTROL_STOP:
>      case SERVICE_CONTROL_SHUTDOWN:
> +        g_mutex_lock(&service_data->mutex);
> +        unmap_drive (service_data->drive_letter);
> +        g_mutex_unlock(&service_data->mutex);
>          quit (SIGTERM);
>          service_status.dwCurrentState = SERVICE_STOP_PENDING;
>          SetServiceStatus (service_status_handle, &service_status);
> @@ -1009,8 +1058,10 @@ service_ctrl_handler (DWORD ctrl, DWORD type, LPVOID data, LPVOID ctx)
>  VOID WINAPI
>  service_main (DWORD argc, TCHAR *argv[])
>  {
> +  ServiceData service_data;
> +
>    service_status_handle =
> -    RegisterServiceCtrlHandlerEx ("spice-webdavd", service_ctrl_handler, NULL);
> +    RegisterServiceCtrlHandlerEx ("spice-webdavd", service_ctrl_handler, &service_data);
> 
>    g_return_if_fail (service_status_handle != 0);
> 
> @@ -1024,7 +1075,7 @@ service_main (DWORD argc, TCHAR *argv[])
>    SetServiceStatus (service_status_handle, &service_status);
> 
>    while (!quit_service) {
> -      run_service ();
> +      run_service (&service_data);
>        g_usleep (G_USEC_PER_SEC);
>    }
> 
> @@ -1048,6 +1099,7 @@ static GOptionEntry entries[] = {
>  int
>  main (int argc, char *argv[])
>  {
> +  ServiceData service_data;
>    GOptionContext *opts;
>    GError *error = NULL;
> 
> @@ -1110,10 +1162,14 @@ main (int argc, char *argv[])
>      } else
>  #endif
>    while (!quit_service) {
> -    run_service ();
> +    run_service (&service_data);
>      g_usleep (G_USEC_PER_SEC);
>    }
> 
> +#ifdef G_OS_WIN32
> +  unmap_drive (service_data.drive_letter);
> +#endif
> +


I guess we could check if it was succesfully mounted before calling
unmap_drive? Maybe you can initialize it with 0 and just check if its
not zero.

Other than that, looks good.
Reviewed-by: Victor Toso <victortoso at redhat.com>

@list, we did some tests and Lukas is opening a few bugs upstream that
we might want to address later on but the auto mount seems to work well.

Cheers,
  toso

>    g_clear_object (&socket_service);
> 
>    return 0;
> --
> 2.5.5
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel


More information about the Spice-devel mailing list