Skip to content

Commit f7d98a0

Browse files
committed
Add rwlock to Subscriptions and subscription objects since we send
events from a background thread.
1 parent d777133 commit f7d98a0

3 files changed

Lines changed: 99 additions & 37 deletions

File tree

scheduler/ipp.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4912,6 +4912,8 @@ copy_subscription_attrs(
49124912

49134913
cupsdLogClient(con, CUPSD_LOG_DEBUG2, "copy_subscription_attrs: sub=%p, ra=%p, exclude=%p", (void *)sub, (void *)ra, (void *)exclude);
49144914

4915+
cupsRWLockRead(&sub->lock);
4916+
49154917
/*
49164918
* Copy the subscription attributes to the response using the
49174919
* requested-attributes attribute that may be provided by the client.
@@ -4999,6 +5001,8 @@ copy_subscription_attrs(
49995001
if (!ra || cupsArrayFind(ra, "notify-subscription-id"))
50005002
ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
50015003
"notify-subscription-id", sub->id);
5004+
5005+
cupsRWUnlock(&sub->lock);
50025006
}
50035007

50045008

@@ -5255,7 +5259,6 @@ create_local_bg_thread(
52555259
goto finish_response;
52565260
}
52575261

5258-
// TODO: Grab printer icon file...
52595262
httpClose(http);
52605263

52615264
/*
@@ -7685,7 +7688,9 @@ get_subscriptions(cupsd_client_t *con, /* I - Client connection */
76857688
ipp_attribute_t *uri) /* I - Printer/job URI */
76867689
{
76877690
http_status_t status; /* Policy status */
7688-
int count; /* Number of subscriptions */
7691+
int i, /* Looping var */
7692+
scount; /* Total number of subscriptions */
7693+
int count; /* Number of subscriptions returned */
76897694
int limit; /* Limit */
76907695
cupsd_subscription_t *sub; /* Subscription */
76917696
cups_array_t *ra; /* Requested attributes array */
@@ -7805,9 +7810,12 @@ get_subscriptions(cupsd_client_t *con, /* I - Client connection */
78057810
else
78067811
username[0] = '\0';
78077812

7808-
for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions), count = 0;
7809-
sub;
7810-
sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
7813+
cupsRWLockRead(&SubscriptionsLock);
7814+
7815+
for (i = 0, count = 0, scount = cupsArrayGetCount(Subscriptions); i < scount; i ++)
7816+
{
7817+
sub = (cupsd_subscription_t *)cupsArrayGetElement(Subscriptions, i);
7818+
78117819
if ((!printer || sub->dest == printer) && (!job || sub->job == job) &&
78127820
(!username[0] || !_cups_strcasecmp(username, sub->owner)))
78137821
{
@@ -7823,6 +7831,9 @@ get_subscriptions(cupsd_client_t *con, /* I - Client connection */
78237831
if (limit && count >= limit)
78247832
break;
78257833
}
7834+
}
7835+
7836+
cupsRWUnlock(&SubscriptionsLock);
78267837

78277838
cupsArrayDelete(ra);
78287839

@@ -9158,6 +9169,8 @@ renew_subscription(
91589169
* Renew the subscription...
91599170
*/
91609171

9172+
cupsRWLockWrite(&sub->lock);
9173+
91619174
lease = ippFindAttribute(con->request, "notify-lease-duration",
91629175
IPP_TAG_INTEGER);
91639176

@@ -9171,6 +9184,8 @@ renew_subscription(
91719184

91729185
sub->expire = sub->lease ? time(NULL) + sub->lease : 0;
91739186

9187+
cupsRWUnlock(&sub->lock);
9188+
91749189
cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
91759190

91769191
con->response->request.status.status_code = IPP_STATUS_OK;

scheduler/subscriptions.c

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
static int cupsd_compare_subscriptions(cupsd_subscription_t *first,
2828
cupsd_subscription_t *second,
2929
void *unused);
30-
static void cupsd_delete_event(cupsd_event_t *event, void *data);
30+
static void cupsd_delete_event(cupsd_event_t *event, void *data);
3131
#ifdef HAVE_DBUS
3232
static void cupsd_send_dbus(cupsd_eventmask_t event, cupsd_printer_t *dest,
3333
cupsd_job_t *job);
@@ -50,10 +50,12 @@ cupsdAddEvent(
5050
const char *text, /* I - Notification text */
5151
...) /* I - Additional arguments as needed */
5252
{
53+
int i, /* Looping var */
54+
scount; /* Number of subscriptions */
5355
va_list ap; /* Pointer to additional arguments */
5456
char ftext[1024]; /* Formatted text buffer */
5557
ipp_attribute_t *attr; /* Printer/job attribute */
56-
cupsd_event_t *temp; /* New event pointer */
58+
cupsd_event_t *temp = NULL; /* New event pointer */
5759
cupsd_subscription_t *sub; /* Current subscription */
5860

5961

@@ -92,14 +94,16 @@ cupsdAddEvent(
9294
if (job && !dest)
9395
dest = cupsdFindPrinter(job->dest);
9496

95-
for (temp = NULL, sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
96-
sub;
97-
sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
97+
cupsRWLockRead(&SubscriptionsLock);
98+
99+
for (i = 0, scount = cupsArrayGetCount(Subscriptions); i < scount; i ++)
98100
{
99101
/*
100102
* Check if this subscription requires this event...
101103
*/
102104

105+
sub = (cupsd_subscription_t *)cupsArrayGetElement(Subscriptions, i);
106+
103107
if ((sub->mask & event) != 0 && (sub->dest == dest || !sub->dest || sub->job == job))
104108
{
105109
/*
@@ -111,6 +115,7 @@ cupsdAddEvent(
111115
cupsdLogMessage(CUPSD_LOG_CRIT,
112116
"Unable to allocate memory for event - %s",
113117
strerror(errno));
118+
cupsRWUnlock(&SubscriptionsLock);
114119
return;
115120
}
116121

@@ -240,6 +245,8 @@ cupsdAddEvent(
240245
}
241246
}
242247

248+
cupsRWUnlock(&SubscriptionsLock);
249+
243250
if (temp)
244251
cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
245252
else
@@ -268,6 +275,8 @@ cupsdAddSubscription(
268275
mask, (void *)dest, dest ? dest->name : "", (void *)job, job ? job->id : 0,
269276
uri ? uri : "(null)");
270277

278+
cupsRWLockWrite(&SubscriptionsLock);
279+
271280
if (!Subscriptions)
272281
Subscriptions = cupsArrayNew((cups_array_func_t)cupsd_compare_subscriptions,
273282
NULL);
@@ -277,6 +286,7 @@ cupsdAddSubscription(
277286
cupsdLogMessage(CUPSD_LOG_CRIT,
278287
"Unable to allocate memory for subscriptions - %s",
279288
strerror(errno));
289+
cupsRWUnlock(&SubscriptionsLock);
280290
return (NULL);
281291
}
282292

@@ -290,6 +300,7 @@ cupsdAddSubscription(
290300
"cupsdAddSubscription: Reached MaxSubscriptions %d "
291301
"(count=%d)", MaxSubscriptions,
292302
cupsArrayCount(Subscriptions));
303+
cupsRWUnlock(&SubscriptionsLock);
293304
return (NULL);
294305
}
295306

@@ -310,6 +321,7 @@ cupsdAddSubscription(
310321
"cupsdAddSubscription: Reached MaxSubscriptionsPerJob %d "
311322
"for job #%d (count=%d)", MaxSubscriptionsPerJob,
312323
job->id, count);
324+
cupsRWUnlock(&SubscriptionsLock);
313325
return (NULL);
314326
}
315327
}
@@ -331,6 +343,7 @@ cupsdAddSubscription(
331343
"cupsdAddSubscription: Reached "
332344
"MaxSubscriptionsPerPrinter %d for %s (count=%d)",
333345
MaxSubscriptionsPerPrinter, dest->name, count);
346+
cupsRWUnlock(&SubscriptionsLock);
334347
return (NULL);
335348
}
336349
}
@@ -344,9 +357,12 @@ cupsdAddSubscription(
344357
cupsdLogMessage(CUPSD_LOG_CRIT,
345358
"Unable to allocate memory for subscription object - %s",
346359
strerror(errno));
360+
cupsRWUnlock(&SubscriptionsLock);
347361
return (NULL);
348362
}
349363

364+
cupsRWInit(&temp->lock);
365+
350366
/*
351367
* Fill in common data...
352368
*/
@@ -380,6 +396,8 @@ cupsdAddSubscription(
380396

381397
cupsArrayAdd(Subscriptions, temp);
382398

399+
cupsRWUnlock(&SubscriptionsLock);
400+
383401
/*
384402
* For RSS subscriptions, run the notifier immediately...
385403
*/
@@ -404,13 +422,17 @@ cupsdDeleteAllSubscriptions(void)
404422
if (!Subscriptions)
405423
return;
406424

425+
cupsRWLockWrite(&SubscriptionsLock);
426+
407427
for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
408428
sub;
409429
sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
410430
cupsdDeleteSubscription(sub, 0);
411431

412432
cupsArrayDelete(Subscriptions);
413433
Subscriptions = NULL;
434+
435+
cupsRWUnlock(&SubscriptionsLock);
414436
}
415437

416438

@@ -434,12 +456,18 @@ cupsdDeleteSubscription(
434456
* Remove subscription from array...
435457
*/
436458

459+
cupsRWLockWrite(&SubscriptionsLock);
460+
437461
cupsArrayRemove(Subscriptions, sub);
438462

463+
cupsRWUnlock(&SubscriptionsLock);
464+
439465
/*
440466
* Free memory...
441467
*/
442468

469+
cupsRWDestroy(&sub->lock);
470+
443471
cupsdClearString(&(sub->owner));
444472
cupsdClearString(&(sub->recipient));
445473

@@ -651,12 +679,18 @@ cupsdExpireSubscriptions(
651679
cupsd_subscription_t * /* O - Subscription object */
652680
cupsdFindSubscription(int id) /* I - Subscription ID */
653681
{
654-
cupsd_subscription_t sub; /* Subscription template */
682+
cupsd_subscription_t key, /* Subscription key */
683+
*sub; /* Matching subscription */
684+
685+
key.id = id;
686+
687+
cupsRWLockRead(&SubscriptionsLock);
655688

689+
sub = (cupsd_subscription_t *)cupsArrayFind(Subscriptions, &sub);
656690

657-
sub.id = id;
691+
cupsRWUnlock(&SubscriptionsLock);
658692

659-
return ((cupsd_subscription_t *)cupsArrayFind(Subscriptions, &sub));
693+
return (sub);
660694
}
661695

662696

@@ -1020,7 +1054,8 @@ cupsdLoadAllSubscriptions(void)
10201054
void
10211055
cupsdSaveAllSubscriptions(void)
10221056
{
1023-
int i; /* Looping var */
1057+
int i, j, /* Looping vars */
1058+
scount; /* Number of subscriptions */
10241059
cups_file_t *fp; /* subscriptions.conf file */
10251060
char filename[1024]; /* subscriptions.conf filename */
10261061
cupsd_subscription_t *sub; /* Current subscription */
@@ -1053,10 +1088,12 @@ cupsdSaveAllSubscriptions(void)
10531088
* Write every subscription known to the system...
10541089
*/
10551090

1056-
for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
1057-
sub;
1058-
sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
1091+
cupsRWLockRead(&SubscriptionsLock);
1092+
1093+
for (i = 0, scount = cupsArrayGetCount(Subscriptions); i < scount; i ++)
10591094
{
1095+
sub = (cupsd_subscription_t *)cupsArrayGetElement(Subscriptions, i);
1096+
10601097
cupsFilePrintf(fp, "<Subscription %d>\n", sub->id);
10611098

10621099
if ((name = cupsdEventName((cupsd_eventmask_t)sub->mask)) != NULL)
@@ -1095,29 +1132,29 @@ cupsdSaveAllSubscriptions(void)
10951132
{
10961133
cupsFilePuts(fp, "UserData ");
10971134

1098-
for (i = 0, hex = 0; i < sub->user_data_len; i ++)
1135+
for (j = 0, hex = 0; j < sub->user_data_len; j ++)
10991136
{
1100-
if (sub->user_data[i] < ' ' ||
1101-
sub->user_data[i] > 0x7f ||
1102-
sub->user_data[i] == '<')
1137+
if (sub->user_data[j] < ' ' ||
1138+
sub->user_data[j] > 0x7f ||
1139+
sub->user_data[j] == '<')
11031140
{
11041141
if (!hex)
11051142
{
1106-
cupsFilePrintf(fp, "<%02X", sub->user_data[i]);
1143+
cupsFilePrintf(fp, "<%02X", sub->user_data[j]);
11071144
hex = 1;
11081145
}
11091146
else
1110-
cupsFilePrintf(fp, "%02X", sub->user_data[i]);
1147+
cupsFilePrintf(fp, "%02X", sub->user_data[j]);
11111148
}
11121149
else
11131150
{
11141151
if (hex)
11151152
{
1116-
cupsFilePrintf(fp, ">%c", sub->user_data[i]);
1153+
cupsFilePrintf(fp, ">%c", sub->user_data[j]);
11171154
hex = 0;
11181155
}
11191156
else
1120-
cupsFilePutChar(fp, sub->user_data[i]);
1157+
cupsFilePutChar(fp, sub->user_data[j]);
11211158
}
11221159
}
11231160

@@ -1135,6 +1172,8 @@ cupsdSaveAllSubscriptions(void)
11351172
cupsFilePuts(fp, "</Subscription>\n");
11361173
}
11371174

1175+
cupsRWUnlock(&SubscriptionsLock);
1176+
11381177
cupsdCloseCreatedConfFile(fp, filename);
11391178
}
11401179

@@ -1326,6 +1365,8 @@ cupsd_send_notification(
13261365
* Allocate the events array as needed...
13271366
*/
13281367

1368+
cupsRWLockWrite(&sub->lock);
1369+
13291370
if (!sub->events)
13301371
{
13311372
sub->events = cupsArrayNew3((cups_array_func_t)NULL, NULL,
@@ -1425,6 +1466,8 @@ cupsd_send_notification(
14251466
*/
14261467

14271468
sub->next_event_id ++;
1469+
1470+
cupsRWUnlock(&sub->lock);
14281471
}
14291472

14301473

0 commit comments

Comments
 (0)