@@ -932,6 +932,9 @@ static int report_delta_progress(
932
932
{
933
933
int ret ;
934
934
935
+ if (pb -> failure )
936
+ return pb -> failure ;
937
+
935
938
if (pb -> progress_cb ) {
936
939
uint64_t current_time = git_time_monotonic ();
937
940
uint64_t elapsed = current_time - pb -> last_progress_report_time ;
@@ -943,8 +946,10 @@ static int report_delta_progress(
943
946
GIT_PACKBUILDER_DELTAFICATION ,
944
947
count , pb -> nr_objects , pb -> progress_cb_payload );
945
948
946
- if (ret )
949
+ if (ret ) {
950
+ pb -> failure = ret ;
947
951
return git_error_set_after_callback (ret );
952
+ }
948
953
}
949
954
}
950
955
@@ -976,7 +981,10 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list,
976
981
}
977
982
978
983
pb -> nr_deltified += 1 ;
979
- report_delta_progress (pb , pb -> nr_deltified , false);
984
+ if ((error = report_delta_progress (pb , pb -> nr_deltified , false)) < 0 ) {
985
+ GIT_ASSERT (git_packbuilder__progress_unlock (pb ) == 0 );
986
+ goto on_error ;
987
+ }
980
988
981
989
po = * list ++ ;
982
990
(* list_size )-- ;
@@ -1124,6 +1132,10 @@ struct thread_params {
1124
1132
size_t depth ;
1125
1133
size_t working ;
1126
1134
size_t data_ready ;
1135
+
1136
+ /* A pb->progress_cb can stop the packing process by returning an error.
1137
+ When that happens, all threads observe the error and stop voluntarily. */
1138
+ bool stopped ;
1127
1139
};
1128
1140
1129
1141
static void * threaded_find_deltas (void * arg )
@@ -1133,7 +1145,12 @@ static void *threaded_find_deltas(void *arg)
1133
1145
while (me -> remaining ) {
1134
1146
if (find_deltas (me -> pb , me -> list , & me -> remaining ,
1135
1147
me -> window , me -> depth ) < 0 ) {
1136
- ; /* TODO */
1148
+ me -> stopped = true;
1149
+ GIT_ASSERT_WITH_RETVAL (git_packbuilder__progress_lock (me -> pb ) == 0 , NULL );
1150
+ me -> working = false;
1151
+ git_cond_signal (& me -> pb -> progress_cond );
1152
+ GIT_ASSERT_WITH_RETVAL (git_packbuilder__progress_unlock (me -> pb ) == 0 , NULL );
1153
+ return NULL ;
1137
1154
}
1138
1155
1139
1156
GIT_ASSERT_WITH_RETVAL (git_packbuilder__progress_lock (me -> pb ) == 0 , NULL );
@@ -1175,8 +1192,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
1175
1192
pb -> nr_threads = git__online_cpus ();
1176
1193
1177
1194
if (pb -> nr_threads <= 1 ) {
1178
- find_deltas (pb , list , & list_size , window , depth );
1179
- return 0 ;
1195
+ return find_deltas (pb , list , & list_size , window , depth );
1180
1196
}
1181
1197
1182
1198
p = git__mallocarray (pb -> nr_threads , sizeof (* p ));
@@ -1195,6 +1211,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
1195
1211
p [i ].depth = depth ;
1196
1212
p [i ].working = 1 ;
1197
1213
p [i ].data_ready = 0 ;
1214
+ p [i ].stopped = 0 ;
1198
1215
1199
1216
/* try to split chunks on "path" boundaries */
1200
1217
while (sub_size && sub_size < list_size &&
@@ -1262,7 +1279,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
1262
1279
(!victim || victim -> remaining < p [i ].remaining ))
1263
1280
victim = & p [i ];
1264
1281
1265
- if (victim ) {
1282
+ if (victim && ! target -> stopped ) {
1266
1283
sub_size = victim -> remaining / 2 ;
1267
1284
list = victim -> list + victim -> list_size - sub_size ;
1268
1285
while (sub_size && list [0 ]-> hash &&
@@ -1286,7 +1303,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
1286
1303
}
1287
1304
target -> list_size = sub_size ;
1288
1305
target -> remaining = sub_size ;
1289
- target -> working = 1 ;
1306
+ target -> working = 1 ; /* even when target->stopped, so that we don't process this thread again */
1290
1307
GIT_ASSERT (git_packbuilder__progress_unlock (pb ) == 0 );
1291
1308
1292
1309
if (git_mutex_lock (& target -> mutex )) {
@@ -1299,7 +1316,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
1299
1316
git_cond_signal (& target -> cond );
1300
1317
git_mutex_unlock (& target -> mutex );
1301
1318
1302
- if (!sub_size ) {
1319
+ if (target -> stopped || !sub_size ) {
1303
1320
git_thread_join (& target -> thread , NULL );
1304
1321
git_cond_free (& target -> cond );
1305
1322
git_mutex_free (& target -> mutex );
@@ -1308,7 +1325,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
1308
1325
}
1309
1326
1310
1327
git__free (p );
1311
- return 0 ;
1328
+ return pb -> failure ;
1312
1329
}
1313
1330
1314
1331
#else
@@ -1319,6 +1336,7 @@ int git_packbuilder__prepare(git_packbuilder *pb)
1319
1336
{
1320
1337
git_pobject * * delta_list ;
1321
1338
size_t i , n = 0 ;
1339
+ int error ;
1322
1340
1323
1341
if (pb -> nr_objects == 0 || pb -> done )
1324
1342
return 0 ; /* nothing to do */
@@ -1327,8 +1345,10 @@ int git_packbuilder__prepare(git_packbuilder *pb)
1327
1345
* Although we do not report progress during deltafication, we
1328
1346
* at least report that we are in the deltafication stage
1329
1347
*/
1330
- if (pb -> progress_cb )
1331
- pb -> progress_cb (GIT_PACKBUILDER_DELTAFICATION , 0 , pb -> nr_objects , pb -> progress_cb_payload );
1348
+ if (pb -> progress_cb ) {
1349
+ if ((error = pb -> progress_cb (GIT_PACKBUILDER_DELTAFICATION , 0 , pb -> nr_objects , pb -> progress_cb_payload )) < 0 )
1350
+ return git_error_set_after_callback (error );
1351
+ }
1332
1352
1333
1353
delta_list = git__mallocarray (pb -> nr_objects , sizeof (* delta_list ));
1334
1354
GIT_ERROR_CHECK_ALLOC (delta_list );
@@ -1345,31 +1365,33 @@ int git_packbuilder__prepare(git_packbuilder *pb)
1345
1365
1346
1366
if (n > 1 ) {
1347
1367
git__tsort ((void * * )delta_list , n , type_size_sort );
1348
- if (ll_find_deltas (pb , delta_list , n ,
1368
+ if (( error = ll_find_deltas (pb , delta_list , n ,
1349
1369
GIT_PACK_WINDOW + 1 ,
1350
- GIT_PACK_DEPTH ) < 0 ) {
1370
+ GIT_PACK_DEPTH )) < 0 ) {
1351
1371
git__free (delta_list );
1352
- return -1 ;
1372
+ return error ;
1353
1373
}
1354
1374
}
1355
1375
1356
- report_delta_progress (pb , pb -> nr_objects , true);
1376
+ error = report_delta_progress (pb , pb -> nr_objects , true);
1357
1377
1358
1378
pb -> done = true;
1359
1379
git__free (delta_list );
1360
- return 0 ;
1380
+ return error ;
1361
1381
}
1362
1382
1363
- #define PREPARE_PACK if ( git_packbuilder__prepare(pb) < 0) { return -1 ; }
1383
+ #define PREPARE_PACK error = git_packbuilder__prepare(pb); if (error < 0) { return error ; }
1364
1384
1365
1385
int git_packbuilder_foreach (git_packbuilder * pb , int (* cb )(void * buf , size_t size , void * payload ), void * payload )
1366
1386
{
1387
+ int error ;
1367
1388
PREPARE_PACK ;
1368
1389
return write_pack (pb , cb , payload );
1369
1390
}
1370
1391
1371
1392
int git_packbuilder__write_buf (git_str * buf , git_packbuilder * pb )
1372
1393
{
1394
+ int error ;
1373
1395
PREPARE_PACK ;
1374
1396
1375
1397
return write_pack (pb , & write_pack_buf , buf );
0 commit comments