]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Add rwlock to Subscriptions and subscription objects since we send
authorMichael R Sweet <msweet@msweet.org>
Thu, 17 Apr 2025 18:34:53 +0000 (14:34 -0400)
committerMichael R Sweet <msweet@msweet.org>
Thu, 17 Apr 2025 18:34:53 +0000 (14:34 -0400)
events from a background thread.

scheduler/ipp.c
scheduler/subscriptions.c
scheduler/subscriptions.h

index a00a7df19eed1880f6326e5331b9412ddb5e1fb5..0708fb85dbe51dd53cda826e0b8e609d4054eccc 100644 (file)
@@ -4912,6 +4912,8 @@ copy_subscription_attrs(
 
   cupsdLogClient(con, CUPSD_LOG_DEBUG2, "copy_subscription_attrs: sub=%p, ra=%p, exclude=%p", (void *)sub, (void *)ra, (void *)exclude);
 
+  cupsRWLockRead(&sub->lock);
+
  /*
   * Copy the subscription attributes to the response using the
   * requested-attributes attribute that may be provided by the client.
@@ -4999,6 +5001,8 @@ copy_subscription_attrs(
   if (!ra || cupsArrayFind(ra, "notify-subscription-id"))
     ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
                   "notify-subscription-id", sub->id);
+
+  cupsRWUnlock(&sub->lock);
 }
 
 
@@ -5255,7 +5259,6 @@ create_local_bg_thread(
     goto finish_response;
   }
 
-  // TODO: Grab printer icon file...
   httpClose(http);
 
  /*
@@ -7685,7 +7688,9 @@ get_subscriptions(cupsd_client_t  *con,   /* I - Client connection */
                   ipp_attribute_t *uri)        /* I - Printer/job URI */
 {
   http_status_t                status;         /* Policy status */
-  int                  count;          /* Number of subscriptions */
+  int                  i,              /* Looping var */
+                       scount;         /* Total number of subscriptions */
+  int                  count;          /* Number of subscriptions returned */
   int                  limit;          /* Limit */
   cupsd_subscription_t *sub;           /* Subscription */
   cups_array_t         *ra;            /* Requested attributes array */
@@ -7805,9 +7810,12 @@ get_subscriptions(cupsd_client_t  *con,  /* I - Client connection */
   else
     username[0] = '\0';
 
-  for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions), count = 0;
-       sub;
-       sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
+  cupsRWLockRead(&SubscriptionsLock);
+
+  for (i = 0, count = 0, scount = cupsArrayGetCount(Subscriptions); i < scount; i ++)
+  {
+    sub = (cupsd_subscription_t *)cupsArrayGetElement(Subscriptions, i);
+
     if ((!printer || sub->dest == printer) && (!job || sub->job == job) &&
         (!username[0] || !_cups_strcasecmp(username, sub->owner)))
     {
@@ -7823,6 +7831,9 @@ get_subscriptions(cupsd_client_t  *con,   /* I - Client connection */
       if (limit && count >= limit)
         break;
     }
+  }
+
+  cupsRWUnlock(&SubscriptionsLock);
 
   cupsArrayDelete(ra);
 
@@ -9158,6 +9169,8 @@ renew_subscription(
   * Renew the subscription...
   */
 
+  cupsRWLockWrite(&sub->lock);
+
   lease = ippFindAttribute(con->request, "notify-lease-duration",
                            IPP_TAG_INTEGER);
 
@@ -9171,6 +9184,8 @@ renew_subscription(
 
   sub->expire = sub->lease ? time(NULL) + sub->lease : 0;
 
+  cupsRWUnlock(&sub->lock);
+
   cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
 
   con->response->request.status.status_code = IPP_STATUS_OK;
index f10b217164d9328fd77509aec97d51d26a782e68..565cdd65f7df1574ed2c504c699fd5b36e7d24ae 100644 (file)
@@ -27,7 +27,7 @@
 static int     cupsd_compare_subscriptions(cupsd_subscription_t *first,
                                            cupsd_subscription_t *second,
                                            void *unused);
-static void cupsd_delete_event(cupsd_event_t *event, void *data);
+static void    cupsd_delete_event(cupsd_event_t *event, void *data);
 #ifdef HAVE_DBUS
 static void    cupsd_send_dbus(cupsd_eventmask_t event, cupsd_printer_t *dest,
                                cupsd_job_t *job);
@@ -50,10 +50,12 @@ cupsdAddEvent(
     const char       *text,            /* I - Notification text */
     ...)                               /* I - Additional arguments as needed */
 {
+  int                  i,              /* Looping var */
+                       scount;         /* Number of subscriptions */
   va_list              ap;             /* Pointer to additional arguments */
   char                 ftext[1024];    /* Formatted text buffer */
   ipp_attribute_t      *attr;          /* Printer/job attribute */
-  cupsd_event_t                *temp;          /* New event pointer */
+  cupsd_event_t                *temp = NULL;   /* New event pointer */
   cupsd_subscription_t *sub;           /* Current subscription */
 
 
@@ -92,14 +94,16 @@ cupsdAddEvent(
   if (job && !dest)
     dest = cupsdFindPrinter(job->dest);
 
-  for (temp = NULL, sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
-       sub;
-       sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
+  cupsRWLockRead(&SubscriptionsLock);
+
+  for (i = 0, scount = cupsArrayGetCount(Subscriptions); i < scount; i ++)
   {
    /*
     * Check if this subscription requires this event...
     */
 
+    sub = (cupsd_subscription_t *)cupsArrayGetElement(Subscriptions, i);
+
     if ((sub->mask & event) != 0 && (sub->dest == dest || !sub->dest || sub->job == job))
     {
      /*
@@ -111,6 +115,7 @@ cupsdAddEvent(
        cupsdLogMessage(CUPSD_LOG_CRIT,
                        "Unable to allocate memory for event - %s",
                        strerror(errno));
+        cupsRWUnlock(&SubscriptionsLock);
        return;
       }
 
@@ -240,6 +245,8 @@ cupsdAddEvent(
     }
   }
 
+  cupsRWUnlock(&SubscriptionsLock);
+
   if (temp)
     cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
   else
@@ -268,6 +275,8 @@ cupsdAddSubscription(
                  mask, (void *)dest, dest ? dest->name : "", (void *)job, job ? job->id : 0,
                  uri ? uri : "(null)");
 
+  cupsRWLockWrite(&SubscriptionsLock);
+
   if (!Subscriptions)
     Subscriptions = cupsArrayNew((cups_array_func_t)cupsd_compare_subscriptions,
                                 NULL);
@@ -277,6 +286,7 @@ cupsdAddSubscription(
     cupsdLogMessage(CUPSD_LOG_CRIT,
                    "Unable to allocate memory for subscriptions - %s",
                    strerror(errno));
+    cupsRWUnlock(&SubscriptionsLock);
     return (NULL);
   }
 
@@ -290,6 +300,7 @@ cupsdAddSubscription(
                    "cupsdAddSubscription: Reached MaxSubscriptions %d "
                    "(count=%d)", MaxSubscriptions,
                    cupsArrayCount(Subscriptions));
+    cupsRWUnlock(&SubscriptionsLock);
     return (NULL);
   }
 
@@ -310,6 +321,7 @@ cupsdAddSubscription(
                      "cupsdAddSubscription: Reached MaxSubscriptionsPerJob %d "
                      "for job #%d (count=%d)", MaxSubscriptionsPerJob,
                      job->id, count);
+      cupsRWUnlock(&SubscriptionsLock);
       return (NULL);
     }
   }
@@ -331,6 +343,7 @@ cupsdAddSubscription(
                      "cupsdAddSubscription: Reached "
                      "MaxSubscriptionsPerPrinter %d for %s (count=%d)",
                      MaxSubscriptionsPerPrinter, dest->name, count);
+      cupsRWUnlock(&SubscriptionsLock);
       return (NULL);
     }
   }
@@ -344,9 +357,12 @@ cupsdAddSubscription(
     cupsdLogMessage(CUPSD_LOG_CRIT,
                    "Unable to allocate memory for subscription object - %s",
                    strerror(errno));
+    cupsRWUnlock(&SubscriptionsLock);
     return (NULL);
   }
 
+  cupsRWInit(&temp->lock);
+
  /*
   * Fill in common data...
   */
@@ -380,6 +396,8 @@ cupsdAddSubscription(
 
   cupsArrayAdd(Subscriptions, temp);
 
+  cupsRWUnlock(&SubscriptionsLock);
+
  /*
   * For RSS subscriptions, run the notifier immediately...
   */
@@ -404,6 +422,8 @@ cupsdDeleteAllSubscriptions(void)
   if (!Subscriptions)
     return;
 
+  cupsRWLockWrite(&SubscriptionsLock);
+
   for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
        sub;
        sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
@@ -411,6 +431,8 @@ cupsdDeleteAllSubscriptions(void)
 
   cupsArrayDelete(Subscriptions);
   Subscriptions = NULL;
+
+  cupsRWUnlock(&SubscriptionsLock);
 }
 
 
@@ -434,12 +456,18 @@ cupsdDeleteSubscription(
   * Remove subscription from array...
   */
 
+  cupsRWLockWrite(&SubscriptionsLock);
+
   cupsArrayRemove(Subscriptions, sub);
 
+  cupsRWUnlock(&SubscriptionsLock);
+
  /*
   * Free memory...
   */
 
+  cupsRWDestroy(&sub->lock);
+
   cupsdClearString(&(sub->owner));
   cupsdClearString(&(sub->recipient));
 
@@ -651,12 +679,18 @@ cupsdExpireSubscriptions(
 cupsd_subscription_t *                 /* O - Subscription object */
 cupsdFindSubscription(int id)          /* I - Subscription ID */
 {
-  cupsd_subscription_t sub;            /* Subscription template */
+  cupsd_subscription_t key,            /* Subscription key */
+                       *sub;           /* Matching subscription */
+
+  key.id = id;
+
+  cupsRWLockRead(&SubscriptionsLock);
 
+  sub = (cupsd_subscription_t *)cupsArrayFind(Subscriptions, &sub);
 
-  sub.id = id;
+  cupsRWUnlock(&SubscriptionsLock);
 
-  return ((cupsd_subscription_t *)cupsArrayFind(Subscriptions, &sub));
+  return (sub);
 }
 
 
@@ -1020,7 +1054,8 @@ cupsdLoadAllSubscriptions(void)
 void
 cupsdSaveAllSubscriptions(void)
 {
-  int                  i;              /* Looping var */
+  int                  i, j,           /* Looping vars */
+                       scount;         /* Number of subscriptions */
   cups_file_t          *fp;            /* subscriptions.conf file */
   char                 filename[1024]; /* subscriptions.conf filename */
   cupsd_subscription_t *sub;           /* Current subscription */
@@ -1053,10 +1088,12 @@ cupsdSaveAllSubscriptions(void)
   * Write every subscription known to the system...
   */
 
-  for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
-       sub;
-       sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
+  cupsRWLockRead(&SubscriptionsLock);
+
+  for (i = 0, scount = cupsArrayGetCount(Subscriptions); i < scount; i ++)
   {
+    sub = (cupsd_subscription_t *)cupsArrayGetElement(Subscriptions, i);
+
     cupsFilePrintf(fp, "<Subscription %d>\n", sub->id);
 
     if ((name = cupsdEventName((cupsd_eventmask_t)sub->mask)) != NULL)
@@ -1095,29 +1132,29 @@ cupsdSaveAllSubscriptions(void)
     {
       cupsFilePuts(fp, "UserData ");
 
-      for (i = 0, hex = 0; i < sub->user_data_len; i ++)
+      for (j = 0, hex = 0; j < sub->user_data_len; j ++)
       {
-       if (sub->user_data[i] < ' ' ||
-           sub->user_data[i] > 0x7f ||
-           sub->user_data[i] == '<')
+       if (sub->user_data[j] < ' ' ||
+           sub->user_data[j] > 0x7f ||
+           sub->user_data[j] == '<')
        {
          if (!hex)
          {
-           cupsFilePrintf(fp, "<%02X", sub->user_data[i]);
+           cupsFilePrintf(fp, "<%02X", sub->user_data[j]);
            hex = 1;
          }
          else
-           cupsFilePrintf(fp, "%02X", sub->user_data[i]);
+           cupsFilePrintf(fp, "%02X", sub->user_data[j]);
        }
        else
        {
          if (hex)
          {
-           cupsFilePrintf(fp, ">%c", sub->user_data[i]);
+           cupsFilePrintf(fp, ">%c", sub->user_data[j]);
            hex = 0;
          }
          else
-           cupsFilePutChar(fp, sub->user_data[i]);
+           cupsFilePutChar(fp, sub->user_data[j]);
        }
       }
 
@@ -1135,6 +1172,8 @@ cupsdSaveAllSubscriptions(void)
     cupsFilePuts(fp, "</Subscription>\n");
   }
 
+  cupsRWUnlock(&SubscriptionsLock);
+
   cupsdCloseCreatedConfFile(fp, filename);
 }
 
@@ -1326,6 +1365,8 @@ cupsd_send_notification(
   * Allocate the events array as needed...
   */
 
+  cupsRWLockWrite(&sub->lock);
+
   if (!sub->events)
   {
     sub->events = cupsArrayNew3((cups_array_func_t)NULL, NULL,
@@ -1425,6 +1466,8 @@ cupsd_send_notification(
   */
 
   sub->next_event_id ++;
+
+  cupsRWUnlock(&sub->lock);
 }
 
 
index bc2a7dcb7018b016c47c19ba949b2b0464fb6d1d..4dc8307b60e64a49520e7297b74da87755b23e7c 100644 (file)
@@ -79,6 +79,7 @@ typedef struct cupsd_event_s          /**** Event structure ****/
 
 typedef struct cupsd_subscription_s    /**** Subscription structure ****/
 {
+  cups_rwlock_t                lock;           /* Reader/writer lock */
   int                  id;             /* subscription-id */
   unsigned             mask;           /* Event mask */
   char                 *owner;         /* notify-subscriber-user-name */
@@ -104,27 +105,30 @@ typedef struct cupsd_subscription_s       /**** Subscription structure ****/
  * Globals...
  */
 
-VAR int                MaxSubscriptions VALUE(100),
+VAR int                MaxSubscriptions        VALUE(100),
                                        /* Overall subscription limit */
-               MaxSubscriptionsPerJob VALUE(0),
+               MaxSubscriptionsPerJob  VALUE(0),
                                        /* Per-job subscription limit */
                MaxSubscriptionsPerPrinter VALUE(0),
                                        /* Per-printer subscription limit */
-               MaxSubscriptionsPerUser VALUE(0),
+               MaxSubscriptionsPerUser VALUE(0),
                                        /* Per-user subscription limit */
-               NextSubscriptionId VALUE(1),
+               NextSubscriptionId      VALUE(1),
                                        /* Next subscription ID */
-               DefaultLeaseDuration VALUE(86400),
+               DefaultLeaseDuration    VALUE(86400),
                                        /* Default notify-lease-duration */
-               MaxLeaseDuration VALUE(0);
+               MaxLeaseDuration        VALUE(0);
                                        /* Maximum notify-lease-duration */
-VAR cups_array_t *Subscriptions VALUE(NULL);
+VAR cups_array_t *Subscriptions                VALUE(NULL);
                                        /* Active subscriptions */
-
-VAR int                MaxEvents VALUE(100);   /* Maximum number of events */
-
-VAR unsigned   LastEvent VALUE(0);     /* Last event(s) processed */
-VAR int                NotifierPipes[2] VALUE2(-1, -1);
+VAR cups_rwlock_t SubscriptionsLock    VALUE(CUPS_RWLOCK_INITIALIZER);
+                                       /* Reader/writer lock for subscriptions */
+VAR int                MaxEvents               VALUE(100);
+                                       /* Maximum number of events */
+
+VAR unsigned   LastEvent               VALUE(0);
+                                       /* Last event(s) processed */
+VAR int                NotifierPipes[2]        VALUE2(-1, -1);
                                        /* Pipes for notifier error/debug output */
 VAR cupsd_statbuf_t *NotifierStatusBuffer VALUE(NULL);
                                        /* Status buffer for pipes */