2.5-18.1
[jlayton/glibc.git] / nptl / tst-cancel4.c
1 /* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 /* NOTE: this tests functionality beyond POSIX.  POSIX does not allow
21    exit to be called more than once.  */
22
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <limits.h>
26 #include <pthread.h>
27 #include <stddef.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <termios.h>
32 #include <unistd.h>
33 #include <sys/mman.h>
34 #include <sys/msg.h>
35 #include <sys/poll.h>
36 #include <sys/select.h>
37 #include <sys/socket.h>
38 #include <sys/uio.h>
39 #include <sys/un.h>
40 #include <sys/wait.h>
41
42 #include "pthreadP.h"
43
44
45 /* Since STREAMS are not supported in the standard Linux kernel and
46    there we don't advertise STREAMS as supported is no need to test
47    the STREAMS related functions.  This affects
48      getmsg()              getpmsg()          putmsg()
49      putpmsg()
50
51    lockf() and fcntl() are tested in tst-cancel16.
52
53    pthread_join() is tested in tst-join5.
54
55    pthread_testcancel()'s only purpose is to allow cancellation.  This
56    is tested in several places.
57
58    sem_wait() and sem_timedwait() are checked in tst-cancel1[2345] tests.
59
60    mq_send(), mq_timedsend(), mq_receive() and mq_timedreceive() are checked
61    in tst-mqueue8{,x} tests.
62
63    aio_suspend() is tested in tst-cancel17.
64
65    clock_nanosleep() is tested in tst-cancel18.
66 */
67
68 /* Pipe descriptors.  */
69 static int fds[2];
70
71 /* Temporary file descriptor, to be closed after each round.  */
72 static int tempfd = -1;
73 static int tempfd2 = -1;
74 /* Name of temporary file to be removed after each round.  */
75 static char *tempfname;
76 /* Temporary message queue.  */
77 static int tempmsg = -1;
78
79 /* Often used barrier for two threads.  */
80 static pthread_barrier_t b2;
81
82
83 #ifndef IPC_ADDVAL
84 # define IPC_ADDVAL 0
85 #endif
86
87 #define WRITE_BUFFER_SIZE 4096
88
89 /* Cleanup handling test.  */
90 static int cl_called;
91
92 static void
93 cl (void *arg)
94 {
95   ++cl_called;
96 }
97
98
99
100 static void *
101 tf_read  (void *arg)
102 {
103   int fd;
104   int r;
105
106   if (arg == NULL)
107     fd = fds[0];
108   else
109     {
110       char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
111       tempfd = fd = mkstemp (fname);
112       if (fd == -1)
113         printf ("%s: mkstemp failed\n", __FUNCTION__);
114       unlink (fname);
115
116       r = pthread_barrier_wait (&b2);
117       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
118         {
119           printf ("%s: barrier_wait failed\n", __FUNCTION__);
120           exit (1);
121         }
122     }
123
124   r = pthread_barrier_wait (&b2);
125   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
126     {
127       printf ("%s: barrier_wait failed\n", __FUNCTION__);
128       exit (1);
129     }
130
131   ssize_t s;
132   pthread_cleanup_push (cl, NULL);
133
134   char buf[100];
135   s = read (fd, buf, sizeof (buf));
136
137   pthread_cleanup_pop (0);
138
139   printf ("%s: read returns with %zd\n", __FUNCTION__, s);
140
141   exit (1);
142 }
143
144
145 static void *
146 tf_readv  (void *arg)
147 {
148   int fd;
149   int r;
150
151   if (arg == NULL)
152     fd = fds[0];
153   else
154     {
155       char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
156       tempfd = fd = mkstemp (fname);
157       if (fd == -1)
158         printf ("%s: mkstemp failed\n", __FUNCTION__);
159       unlink (fname);
160
161       r = pthread_barrier_wait (&b2);
162       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
163         {
164           printf ("%s: barrier_wait failed\n", __FUNCTION__);
165           exit (1);
166         }
167     }
168
169   r = pthread_barrier_wait (&b2);
170   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
171     {
172       printf ("%s: barrier_wait failed\n", __FUNCTION__);
173       exit (1);
174     }
175
176   ssize_t s;
177   pthread_cleanup_push (cl, NULL);
178
179   char buf[100];
180   struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
181   s = readv (fd, iov, 1);
182
183   pthread_cleanup_pop (0);
184
185   printf ("%s: readv returns with %zd\n", __FUNCTION__, s);
186
187   exit (1);
188 }
189
190
191 static void *
192 tf_write  (void *arg)
193 {
194   int fd;
195   int r;
196
197   if (arg == NULL)
198     fd = fds[1];
199   else
200     {
201       char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
202       tempfd = fd = mkstemp (fname);
203       if (fd == -1)
204         printf ("%s: mkstemp failed\n", __FUNCTION__);
205       unlink (fname);
206
207       r = pthread_barrier_wait (&b2);
208       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
209         {
210           printf ("%s: barrier_wait failed\n", __FUNCTION__);
211           exit (1);
212         }
213     }
214
215   r = pthread_barrier_wait (&b2);
216   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
217     {
218       printf ("%s: barrier_wait failed\n", __FUNCTION__);
219       exit (1);
220     }
221
222   ssize_t s;
223   pthread_cleanup_push (cl, NULL);
224
225   char buf[WRITE_BUFFER_SIZE];
226   memset (buf, '\0', sizeof (buf));
227   s = write (fd, buf, sizeof (buf));
228
229   pthread_cleanup_pop (0);
230
231   printf ("%s: write returns with %zd\n", __FUNCTION__, s);
232
233   exit (1);
234 }
235
236
237 static void *
238 tf_writev  (void *arg)
239 {
240   int fd;
241   int r;
242
243   if (arg == NULL)
244     fd = fds[1];
245   else
246     {
247       char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
248       tempfd = fd = mkstemp (fname);
249       if (fd == -1)
250         printf ("%s: mkstemp failed\n", __FUNCTION__);
251       unlink (fname);
252
253       r = pthread_barrier_wait (&b2);
254       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
255         {
256           printf ("%s: barrier_wait failed\n", __FUNCTION__);
257           exit (1);
258         }
259     }
260
261   r = pthread_barrier_wait (&b2);
262   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
263     {
264       printf ("%s: barrier_wait failed\n", __FUNCTION__);
265       exit (1);
266     }
267
268   ssize_t s;
269   pthread_cleanup_push (cl, NULL);
270
271   char buf[WRITE_BUFFER_SIZE];
272   memset (buf, '\0', sizeof (buf));
273   struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
274   s = writev (fd, iov, 1);
275
276   pthread_cleanup_pop (0);
277
278   printf ("%s: writev returns with %zd\n", __FUNCTION__, s);
279
280   exit (1);
281 }
282
283
284 static void *
285 tf_sleep (void *arg)
286 {
287   int r = pthread_barrier_wait (&b2);
288   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
289     {
290       printf ("%s: barrier_wait failed\n", __FUNCTION__);
291       exit (1);
292     }
293
294   if (arg != NULL)
295     {
296       r = pthread_barrier_wait (&b2);
297       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
298         {
299           printf ("%s: barrier_wait failed\n", __FUNCTION__);
300           exit (1);
301         }
302     }
303
304   pthread_cleanup_push (cl, NULL);
305
306   sleep (arg == NULL ? 1000000 : 0);
307
308   pthread_cleanup_pop (0);
309
310   printf ("%s: sleep returns\n", __FUNCTION__);
311
312   exit (1);
313 }
314
315
316 static void *
317 tf_usleep (void *arg)
318 {
319   int r = pthread_barrier_wait (&b2);
320   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
321     {
322       printf ("%s: barrier_wait failed\n", __FUNCTION__);
323       exit (1);
324     }
325
326   if (arg != NULL)
327     {
328       r = pthread_barrier_wait (&b2);
329       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
330         {
331           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
332           exit (1);
333         }
334     }
335
336   pthread_cleanup_push (cl, NULL);
337
338   usleep (arg == NULL ? (useconds_t) ULONG_MAX : 0);
339
340   pthread_cleanup_pop (0);
341
342   printf ("%s: usleep returns\n", __FUNCTION__);
343
344   exit (1);
345 }
346
347
348 static void *
349 tf_nanosleep (void *arg)
350 {
351   int r = pthread_barrier_wait (&b2);
352   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
353     {
354       printf ("%s: barrier_wait failed\n", __FUNCTION__);
355       exit (1);
356     }
357
358   if (arg != NULL)
359     {
360       r = pthread_barrier_wait (&b2);
361       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
362         {
363           printf ("%s: barrier_wait failed\n", __FUNCTION__);
364           exit (1);
365         }
366     }
367
368   pthread_cleanup_push (cl, NULL);
369
370   struct timespec ts = { .tv_sec = arg == NULL ? 10000000 : 0, .tv_nsec = 0 };
371   TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
372
373   pthread_cleanup_pop (0);
374
375   printf ("%s: nanosleep returns\n", __FUNCTION__);
376
377   exit (1);
378 }
379
380
381 static void *
382 tf_select (void *arg)
383 {
384   int fd;
385   int r;
386
387   if (arg == NULL)
388     fd = fds[0];
389   else
390     {
391       char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
392       tempfd = fd = mkstemp (fname);
393       if (fd == -1)
394         printf ("%s: mkstemp failed\n", __FUNCTION__);
395       unlink (fname);
396
397       r = pthread_barrier_wait (&b2);
398       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
399         {
400           printf ("%s: barrier_wait failed\n", __FUNCTION__);
401           exit (1);
402         }
403     }
404
405   r = pthread_barrier_wait (&b2);
406   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
407     {
408       printf ("%s: barrier_wait failed\n", __FUNCTION__);
409       exit (1);
410     }
411
412   fd_set rfs;
413   FD_ZERO (&rfs);
414   FD_SET (fd, &rfs);
415
416   int s;
417   pthread_cleanup_push (cl, NULL);
418
419   s = select (fd + 1, &rfs, NULL, NULL, NULL);
420
421   pthread_cleanup_pop (0);
422
423   printf ("%s: select returns with %d (%s)\n", __FUNCTION__, s,
424           strerror (errno));
425
426   exit (1);
427 }
428
429
430 static void *
431 tf_pselect (void *arg)
432 {
433   int fd;
434   int r;
435
436   if (arg == NULL)
437     fd = fds[0];
438   else
439     {
440       char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
441       tempfd = fd = mkstemp (fname);
442       if (fd == -1)
443         printf ("%s: mkstemp failed\n", __FUNCTION__);
444       unlink (fname);
445
446       r = pthread_barrier_wait (&b2);
447       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
448         {
449           printf ("%s: barrier_wait failed\n", __FUNCTION__);
450           exit (1);
451         }
452     }
453
454   r = pthread_barrier_wait (&b2);
455   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
456     {
457       printf ("%s: barrier_wait failed\n", __FUNCTION__);
458       exit (1);
459     }
460
461   fd_set rfs;
462   FD_ZERO (&rfs);
463   FD_SET (fd, &rfs);
464
465   int s;
466   pthread_cleanup_push (cl, NULL);
467
468   s = pselect (fd + 1, &rfs, NULL, NULL, NULL, NULL);
469
470   pthread_cleanup_pop (0);
471
472   printf ("%s: pselect returns with %d (%s)\n", __FUNCTION__, s,
473           strerror (errno));
474
475   exit (1);
476 }
477
478
479 static void *
480 tf_poll (void *arg)
481 {
482   int fd;
483   int r;
484
485   if (arg == NULL)
486     fd = fds[0];
487   else
488     {
489       char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
490       tempfd = fd = mkstemp (fname);
491       if (fd == -1)
492         printf ("%s: mkstemp failed\n", __FUNCTION__);
493       unlink (fname);
494
495       r = pthread_barrier_wait (&b2);
496       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
497         {
498           printf ("%s: barrier_wait failed\n", __FUNCTION__);
499           exit (1);
500         }
501     }
502
503   r = pthread_barrier_wait (&b2);
504   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
505     {
506       printf ("%s: barrier_wait failed\n", __FUNCTION__);
507       exit (1);
508     }
509
510   struct pollfd rfs[1] = { [0] = { .fd = fd, .events = POLLIN } };
511
512   int s;
513   pthread_cleanup_push (cl, NULL);
514
515   s = poll (rfs, 1, -1);
516
517   pthread_cleanup_pop (0);
518
519   printf ("%s: poll returns with %d (%s)\n", __FUNCTION__, s,
520           strerror (errno));
521
522   exit (1);
523 }
524
525
526 static void *
527 tf_ppoll (void *arg)
528 {
529   int fd;
530   int r;
531
532   if (arg == NULL)
533     fd = fds[0];
534   else
535     {
536       char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
537       tempfd = fd = mkstemp (fname);
538       if (fd == -1)
539         printf ("%s: mkstemp failed\n", __FUNCTION__);
540       unlink (fname);
541
542       r = pthread_barrier_wait (&b2);
543       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
544         {
545           printf ("%s: barrier_wait failed\n", __FUNCTION__);
546           exit (1);
547         }
548     }
549
550   r = pthread_barrier_wait (&b2);
551   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
552     {
553       printf ("%s: barrier_wait failed\n", __FUNCTION__);
554       exit (1);
555     }
556
557   struct pollfd rfs[1] = { [0] = { .fd = fd, .events = POLLIN } };
558
559   int s;
560   pthread_cleanup_push (cl, NULL);
561
562   s = ppoll (rfs, 1, NULL, NULL);
563
564   pthread_cleanup_pop (0);
565
566   printf ("%s: ppoll returns with %d (%s)\n", __FUNCTION__, s,
567           strerror (errno));
568
569   exit (1);
570 }
571
572
573 static void *
574 tf_wait (void *arg)
575 {
576   pid_t pid = fork ();
577   if (pid == -1)
578     {
579       puts ("fork failed");
580       exit (1);
581     }
582
583   if (pid == 0)
584     {
585       /* Make the program disappear after a while.  */
586       if (arg == NULL)
587         sleep (10);
588       exit (0);
589     }
590
591   int r;
592   if (arg != NULL)
593     {
594       struct timespec  ts = { .tv_sec = 0, .tv_nsec = 100000000 };
595       while (nanosleep (&ts, &ts) != 0)
596         continue;
597
598       r = pthread_barrier_wait (&b2);
599       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
600         {
601           printf ("%s: barrier_wait failed\n", __FUNCTION__);
602           exit (1);
603         }
604     }
605
606   r = pthread_barrier_wait (&b2);
607   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
608     {
609       printf ("%s: barrier_wait failed\n", __FUNCTION__);
610       exit (1);
611     }
612
613   int s;
614   pthread_cleanup_push (cl, NULL);
615
616   s = wait (NULL);
617
618   pthread_cleanup_pop (0);
619
620   printf ("%s: wait returns with %d (%s)\n", __FUNCTION__, s,
621           strerror (errno));
622
623   exit (1);
624 }
625
626
627 static void *
628 tf_waitpid (void *arg)
629 {
630
631   pid_t pid = fork ();
632   if (pid == -1)
633     {
634       puts ("fork failed");
635       exit (1);
636     }
637
638   if (pid == 0)
639     {
640       /* Make the program disappear after a while.  */
641       if (arg == NULL)
642         sleep (10);
643       exit (0);
644     }
645
646   int r;
647   if (arg != NULL)
648     {
649       struct timespec  ts = { .tv_sec = 0, .tv_nsec = 100000000 };
650       while (nanosleep (&ts, &ts) != 0)
651         continue;
652
653       r = pthread_barrier_wait (&b2);
654       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
655         {
656           printf ("%s: barrier_wait failed\n", __FUNCTION__);
657           exit (1);
658         }
659     }
660
661   r = pthread_barrier_wait (&b2);
662   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
663     {
664       printf ("%s: barrier_wait failed\n", __FUNCTION__);
665       exit (1);
666     }
667
668   int s;
669  pthread_cleanup_push (cl, NULL);
670
671   s = waitpid (-1, NULL, 0);
672
673   pthread_cleanup_pop (0);
674
675   printf ("%s: waitpid returns with %d (%s)\n", __FUNCTION__, s,
676           strerror (errno));
677
678   exit (1);
679 }
680
681
682 static void *
683 tf_waitid (void *arg)
684 {
685   pid_t pid = fork ();
686   if (pid == -1)
687     {
688       puts ("fork failed");
689       exit (1);
690     }
691
692   if (pid == 0)
693     {
694       /* Make the program disappear after a while.  */
695       if (arg == NULL)
696         sleep (10);
697       exit (0);
698     }
699
700   int r;
701   if (arg != NULL)
702     {
703       struct timespec  ts = { .tv_sec = 0, .tv_nsec = 100000000 };
704       while (nanosleep (&ts, &ts) != 0)
705         continue;
706
707       r = pthread_barrier_wait (&b2);
708       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
709         {
710           printf ("%s: barrier_wait failed\n", __FUNCTION__);
711           exit (1);
712         }
713     }
714
715   r = pthread_barrier_wait (&b2);
716   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
717     {
718       printf ("%s: barrier_wait failed\n", __FUNCTION__);
719       exit (1);
720     }
721
722   int s;
723   pthread_cleanup_push (cl, NULL);
724
725 #ifndef WEXITED
726 # define WEXITED 0
727 #endif
728   siginfo_t si;
729   s = waitid (P_PID, pid, &si, WEXITED);
730
731   pthread_cleanup_pop (0);
732
733   printf ("%s: waitid returns with %d (%s)\n", __FUNCTION__, s,
734           strerror (errno));
735
736   exit (1);
737 }
738
739
740 static void *
741 tf_sigpause (void *arg)
742 {
743   int r = pthread_barrier_wait (&b2);
744   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
745     {
746       printf ("%s: barrier_wait failed\n", __FUNCTION__);
747       exit (1);
748     }
749
750   if (arg != NULL)
751     {
752       r = pthread_barrier_wait (&b2);
753       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
754         {
755           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
756           exit (1);
757         }
758     }
759
760   pthread_cleanup_push (cl, NULL);
761
762   /* Just for fun block the cancellation signal.  We need to use
763      __xpg_sigpause since otherwise we will get the BSD version.  */
764   __xpg_sigpause (SIGCANCEL);
765
766   pthread_cleanup_pop (0);
767
768   printf ("%s: sigpause returned\n", __FUNCTION__);
769
770   exit (1);
771 }
772
773
774 static void *
775 tf_sigsuspend (void *arg)
776 {
777   int r = pthread_barrier_wait (&b2);
778   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
779     {
780       printf ("%s: barrier_wait failed\n", __FUNCTION__);
781       exit (1);
782     }
783
784   if (arg != NULL)
785     {
786       r = pthread_barrier_wait (&b2);
787       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
788         {
789           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
790           exit (1);
791         }
792     }
793
794   pthread_cleanup_push (cl, NULL);
795
796   /* Just for fun block all signals.  */
797   sigset_t mask;
798   sigfillset (&mask);
799   sigsuspend (&mask);
800
801   pthread_cleanup_pop (0);
802
803   printf ("%s: sigsuspend returned\n", __FUNCTION__);
804
805   exit (1);
806 }
807
808
809 static void *
810 tf_sigwait (void *arg)
811 {
812   int r = pthread_barrier_wait (&b2);
813   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
814     {
815       printf ("%s: barrier_wait failed\n", __FUNCTION__);
816       exit (1);
817     }
818
819   if (arg != NULL)
820     {
821       r = pthread_barrier_wait (&b2);
822       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
823         {
824           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
825           exit (1);
826         }
827     }
828
829   /* Block SIGUSR1.  */
830   sigset_t mask;
831   sigemptyset (&mask);
832   sigaddset (&mask, SIGUSR1);
833   if (pthread_sigmask (SIG_BLOCK, &mask, NULL) != 0)
834     {
835       printf ("%s: pthread_sigmask failed\n", __FUNCTION__);
836       exit (1);
837     }
838
839   int sig;
840   pthread_cleanup_push (cl, NULL);
841
842   /* Wait for SIGUSR1.  */
843   sigwait (&mask, &sig);
844
845   pthread_cleanup_pop (0);
846
847   printf ("%s: sigwait returned with signal %d\n", __FUNCTION__, sig);
848
849   exit (1);
850 }
851
852
853 static void *
854 tf_sigwaitinfo (void *arg)
855 {
856   int r = pthread_barrier_wait (&b2);
857   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
858     {
859       printf ("%s: barrier_wait failed\n", __FUNCTION__);
860       exit (1);
861     }
862
863   if (arg != NULL)
864     {
865       r = pthread_barrier_wait (&b2);
866       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
867         {
868           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
869           exit (1);
870         }
871     }
872
873   /* Block SIGUSR1.  */
874   sigset_t mask;
875   sigemptyset (&mask);
876   sigaddset (&mask, SIGUSR1);
877   if (pthread_sigmask (SIG_BLOCK, &mask, NULL) != 0)
878     {
879       printf ("%s: pthread_sigmask failed\n", __FUNCTION__);
880       exit (1);
881     }
882
883   siginfo_t info;
884   pthread_cleanup_push (cl, NULL);
885
886   /* Wait for SIGUSR1.  */
887   sigwaitinfo (&mask, &info);
888
889   pthread_cleanup_pop (0);
890
891   printf ("%s: sigwaitinfo returned with signal %d\n", __FUNCTION__,
892           info.si_signo);
893
894   exit (1);
895 }
896
897
898 static void *
899 tf_sigtimedwait (void *arg)
900 {
901   int r = pthread_barrier_wait (&b2);
902   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
903     {
904       printf ("%s: barrier_wait failed\n", __FUNCTION__);
905       exit (1);
906     }
907
908   if (arg != NULL)
909     {
910       r = pthread_barrier_wait (&b2);
911       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
912         {
913           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
914           exit (1);
915         }
916     }
917
918   /* Block SIGUSR1.  */
919   sigset_t mask;
920   sigemptyset (&mask);
921   sigaddset (&mask, SIGUSR1);
922   if (pthread_sigmask (SIG_BLOCK, &mask, NULL) != 0)
923     {
924       printf ("%s: pthread_sigmask failed\n", __FUNCTION__);
925       exit (1);
926     }
927
928   /* Wait for SIGUSR1.  */
929   siginfo_t info;
930   struct timespec ts = { .tv_sec = 60, .tv_nsec = 0 };
931   pthread_cleanup_push (cl, NULL);
932
933   sigtimedwait (&mask, &info, &ts);
934
935   pthread_cleanup_pop (0);
936
937   printf ("%s: sigtimedwait returned with signal %d\n", __FUNCTION__,
938           info.si_signo);
939
940   exit (1);
941 }
942
943
944 static void *
945 tf_pause (void *arg)
946 {
947   int r = pthread_barrier_wait (&b2);
948   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
949     {
950       printf ("%s: barrier_wait failed\n", __FUNCTION__);
951       exit (1);
952     }
953
954   if (arg != NULL)
955     {
956       r = pthread_barrier_wait (&b2);
957       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
958         {
959           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
960           exit (1);
961         }
962     }
963
964   pthread_cleanup_push (cl, NULL);
965
966   pause ();
967
968   pthread_cleanup_pop (0);
969
970   printf ("%s: pause returned\n", __FUNCTION__);
971
972   exit (1);
973 }
974
975
976 static void *
977 tf_accept (void *arg)
978 {
979   struct sockaddr_un sun;
980   /* To test a non-blocking accept call we make the call file by using
981      a datagrame socket.  */
982   int pf = arg == NULL ? SOCK_STREAM : SOCK_DGRAM;
983
984   tempfd = socket (AF_UNIX, pf, 0);
985   if (tempfd == -1)
986     {
987       printf ("%s: socket call failed\n", __FUNCTION__);
988       exit (1);
989     }
990
991   int tries = 0;
992   do
993     {
994       if (++tries > 10)
995         {
996           printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
997         }
998
999       strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-1-XXXXXX");
1000       if (mktemp (sun.sun_path) == NULL)
1001         {
1002           printf ("%s: cannot generate temp file name\n", __FUNCTION__);
1003           exit (1);
1004         }
1005
1006       sun.sun_family = AF_UNIX;
1007     }
1008   while (bind (tempfd, (struct sockaddr *) &sun,
1009                offsetof (struct sockaddr_un, sun_path)
1010                + strlen (sun.sun_path) + 1) != 0);
1011
1012   unlink (sun.sun_path);
1013
1014   listen (tempfd, 5);
1015
1016   socklen_t len = sizeof (sun);
1017
1018   int r = pthread_barrier_wait (&b2);
1019   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1020     {
1021       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1022       exit (1);
1023     }
1024
1025   if (arg != NULL)
1026     {
1027       r = pthread_barrier_wait (&b2);
1028       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1029         {
1030           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1031           exit (1);
1032         }
1033     }
1034
1035   pthread_cleanup_push (cl, NULL);
1036
1037   accept (tempfd, (struct sockaddr *) &sun, &len);
1038
1039   pthread_cleanup_pop (0);
1040
1041   printf ("%s: accept returned\n", __FUNCTION__);
1042
1043   exit (1);
1044 }
1045
1046
1047 static void *
1048 tf_send (void *arg)
1049 {
1050   struct sockaddr_un sun;
1051
1052   tempfd = socket (AF_UNIX, SOCK_STREAM, 0);
1053   if (tempfd == -1)
1054     {
1055       printf ("%s: first socket call failed\n", __FUNCTION__);
1056       exit (1);
1057     }
1058
1059   int tries = 0;
1060   do
1061     {
1062       if (++tries > 10)
1063         {
1064           printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
1065         }
1066
1067       strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-2-XXXXXX");
1068       if (mktemp (sun.sun_path) == NULL)
1069         {
1070           printf ("%s: cannot generate temp file name\n", __FUNCTION__);
1071           exit (1);
1072         }
1073
1074       sun.sun_family = AF_UNIX;
1075     }
1076   while (bind (tempfd, (struct sockaddr *) &sun,
1077                offsetof (struct sockaddr_un, sun_path)
1078                + strlen (sun.sun_path) + 1) != 0);
1079
1080   listen (tempfd, 5);
1081
1082   tempfd2 = socket (AF_UNIX, SOCK_STREAM, 0);
1083   if (tempfd2 == -1)
1084     {
1085       printf ("%s: second socket call failed\n", __FUNCTION__);
1086       exit (1);
1087     }
1088
1089   if (connect (tempfd2, (struct sockaddr *) &sun, sizeof (sun)) != 0)
1090     {
1091       printf ("%s: connect failed\n", __FUNCTION__);
1092       exit(1);
1093     }
1094
1095   unlink (sun.sun_path);
1096
1097   int r = pthread_barrier_wait (&b2);
1098   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1099     {
1100       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1101       exit (1);
1102     }
1103
1104   if (arg != NULL)
1105     {
1106       r = pthread_barrier_wait (&b2);
1107       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1108         {
1109           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1110           exit (1);
1111         }
1112     }
1113
1114   pthread_cleanup_push (cl, NULL);
1115
1116   /* Very large block, so that the send call blocks.  */
1117   char mem[700000];
1118
1119   send (tempfd2, mem, arg == NULL ? sizeof (mem) : 1, 0);
1120
1121   pthread_cleanup_pop (0);
1122
1123   printf ("%s: send returned\n", __FUNCTION__);
1124
1125   exit (1);
1126 }
1127
1128
1129 static void *
1130 tf_recv (void *arg)
1131 {
1132   struct sockaddr_un sun;
1133
1134   tempfd = socket (AF_UNIX, SOCK_STREAM, 0);
1135   if (tempfd == -1)
1136     {
1137       printf ("%s: first socket call failed\n", __FUNCTION__);
1138       exit (1);
1139     }
1140
1141   int tries = 0;
1142   do
1143     {
1144       if (++tries > 10)
1145         {
1146           printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
1147         }
1148
1149       strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-3-XXXXXX");
1150       if (mktemp (sun.sun_path) == NULL)
1151         {
1152           printf ("%s: cannot generate temp file name\n", __FUNCTION__);
1153           exit (1);
1154         }
1155
1156       sun.sun_family = AF_UNIX;
1157     }
1158   while (bind (tempfd, (struct sockaddr *) &sun,
1159                offsetof (struct sockaddr_un, sun_path)
1160                + strlen (sun.sun_path) + 1) != 0);
1161
1162   listen (tempfd, 5);
1163
1164   tempfd2 = socket (AF_UNIX, SOCK_STREAM, 0);
1165   if (tempfd2 == -1)
1166     {
1167       printf ("%s: second socket call failed\n", __FUNCTION__);
1168       exit (1);
1169     }
1170
1171   if (connect (tempfd2, (struct sockaddr *) &sun, sizeof (sun)) != 0)
1172     {
1173       printf ("%s: connect failed\n", __FUNCTION__);
1174       exit(1);
1175     }
1176
1177   unlink (sun.sun_path);
1178
1179   int r = pthread_barrier_wait (&b2);
1180   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1181     {
1182       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1183       exit (1);
1184     }
1185
1186   if (arg != NULL)
1187     {
1188       r = pthread_barrier_wait (&b2);
1189       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1190         {
1191           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1192           exit (1);
1193         }
1194     }
1195
1196   pthread_cleanup_push (cl, NULL);
1197
1198   char mem[70];
1199
1200   recv (tempfd2, mem, arg == NULL ? sizeof (mem) : 0, 0);
1201
1202   pthread_cleanup_pop (0);
1203
1204   printf ("%s: recv returned\n", __FUNCTION__);
1205
1206   exit (1);
1207 }
1208
1209
1210 static void *
1211 tf_recvfrom (void *arg)
1212 {
1213   struct sockaddr_un sun;
1214
1215   tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
1216   if (tempfd == -1)
1217     {
1218       printf ("%s: first socket call failed\n", __FUNCTION__);
1219       exit (1);
1220     }
1221
1222   int tries = 0;
1223   do
1224     {
1225       if (++tries > 10)
1226         {
1227           printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
1228         }
1229
1230       strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-4-XXXXXX");
1231       if (mktemp (sun.sun_path) == NULL)
1232         {
1233           printf ("%s: cannot generate temp file name\n", __FUNCTION__);
1234           exit (1);
1235         }
1236
1237       sun.sun_family = AF_UNIX;
1238     }
1239   while (bind (tempfd, (struct sockaddr *) &sun,
1240                offsetof (struct sockaddr_un, sun_path)
1241                + strlen (sun.sun_path) + 1) != 0);
1242
1243   tempfname = strdup (sun.sun_path);
1244
1245   tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
1246   if (tempfd2 == -1)
1247     {
1248       printf ("%s: second socket call failed\n", __FUNCTION__);
1249       exit (1);
1250     }
1251
1252   int r = pthread_barrier_wait (&b2);
1253   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1254     {
1255       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1256       exit (1);
1257     }
1258
1259   if (arg != NULL)
1260     {
1261       r = pthread_barrier_wait (&b2);
1262       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1263         {
1264           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1265           exit (1);
1266         }
1267     }
1268
1269   pthread_cleanup_push (cl, NULL);
1270
1271   char mem[70];
1272   socklen_t len = sizeof (sun);
1273
1274   recvfrom (tempfd2, mem, arg == NULL ? sizeof (mem) : 0, 0,
1275             (struct sockaddr *) &sun, &len);
1276
1277   pthread_cleanup_pop (0);
1278
1279   printf ("%s: recvfrom returned\n", __FUNCTION__);
1280
1281   exit (1);
1282 }
1283
1284
1285 static void *
1286 tf_recvmsg (void *arg)
1287 {
1288   struct sockaddr_un sun;
1289
1290   tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
1291   if (tempfd == -1)
1292     {
1293       printf ("%s: first socket call failed\n", __FUNCTION__);
1294       exit (1);
1295     }
1296
1297   int tries = 0;
1298   do
1299     {
1300       if (++tries > 10)
1301         {
1302           printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
1303         }
1304
1305       strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-5-XXXXXX");
1306       if (mktemp (sun.sun_path) == NULL)
1307         {
1308           printf ("%s: cannot generate temp file name\n", __FUNCTION__);
1309           exit (1);
1310         }
1311
1312       sun.sun_family = AF_UNIX;
1313     }
1314   while (bind (tempfd, (struct sockaddr *) &sun,
1315                offsetof (struct sockaddr_un, sun_path)
1316                + strlen (sun.sun_path) + 1) != 0);
1317
1318   tempfname = strdup (sun.sun_path);
1319
1320   tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
1321   if (tempfd2 == -1)
1322     {
1323       printf ("%s: second socket call failed\n", __FUNCTION__);
1324       exit (1);
1325     }
1326
1327   int r = pthread_barrier_wait (&b2);
1328   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1329     {
1330       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1331       exit (1);
1332     }
1333
1334   if (arg != NULL)
1335     {
1336       r = pthread_barrier_wait (&b2);
1337       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1338         {
1339           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1340           exit (1);
1341         }
1342     }
1343
1344   pthread_cleanup_push (cl, NULL);
1345
1346   char mem[70];
1347   struct iovec iov[1];
1348   iov[0].iov_base = mem;
1349   iov[0].iov_len = arg == NULL ? sizeof (mem) : 0;
1350
1351   struct msghdr m;
1352   m.msg_name = &sun;
1353   m.msg_namelen = sizeof (sun);
1354   m.msg_iov = iov;
1355   m.msg_iovlen = 1;
1356   m.msg_control = NULL;
1357   m.msg_controllen = 0;
1358
1359   recvmsg (tempfd2, &m, 0);
1360
1361   pthread_cleanup_pop (0);
1362
1363   printf ("%s: recvmsg returned\n", __FUNCTION__);
1364
1365   exit (1);
1366 }
1367
1368
1369 static void *
1370 tf_open (void *arg)
1371 {
1372   if (arg == NULL)
1373     // XXX If somebody can provide a portable test case in which open()
1374     // blocks we can enable this test to run in both rounds.
1375     abort ();
1376
1377   int r = pthread_barrier_wait (&b2);
1378   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1379     {
1380       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1381       exit (1);
1382     }
1383
1384   r = pthread_barrier_wait (&b2);
1385   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1386     {
1387       printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1388       exit (1);
1389     }
1390
1391   pthread_cleanup_push (cl, NULL);
1392
1393   open ("Makefile", O_RDONLY);
1394
1395   pthread_cleanup_pop (0);
1396
1397   printf ("%s: open returned\n", __FUNCTION__);
1398
1399   exit (1);
1400 }
1401
1402
1403 static void *
1404 tf_close (void *arg)
1405 {
1406   if (arg == NULL)
1407     // XXX If somebody can provide a portable test case in which close()
1408     // blocks we can enable this test to run in both rounds.
1409     abort ();
1410
1411   char fname[] = "/tmp/tst-cancel-fd-XXXXXX";
1412   tempfd = mkstemp (fname);
1413   if (tempfd == -1)
1414     {
1415       printf ("%s: mkstemp failed\n", __FUNCTION__);
1416       exit (1);
1417     }
1418   unlink (fname);
1419
1420   int r = pthread_barrier_wait (&b2);
1421   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1422     {
1423       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1424       exit (1);
1425     }
1426
1427   r = pthread_barrier_wait (&b2);
1428   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1429     {
1430       printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1431       exit (1);
1432     }
1433
1434   pthread_cleanup_push (cl, NULL);
1435
1436   close (tempfd);
1437
1438   pthread_cleanup_pop (0);
1439
1440   printf ("%s: close returned\n", __FUNCTION__);
1441
1442   exit (1);
1443 }
1444
1445
1446 static void *
1447 tf_pread (void *arg)
1448 {
1449   if (arg == NULL)
1450     // XXX If somebody can provide a portable test case in which pread()
1451     // blocks we can enable this test to run in both rounds.
1452     abort ();
1453
1454   tempfd = open ("Makefile", O_RDONLY);
1455   if (tempfd == -1)
1456     {
1457       printf ("%s: cannot open Makefile\n", __FUNCTION__);
1458       exit (1);
1459     }
1460
1461   int r = pthread_barrier_wait (&b2);
1462   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1463     {
1464       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1465       exit (1);
1466     }
1467
1468   r = pthread_barrier_wait (&b2);
1469   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1470     {
1471       printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1472       exit (1);
1473     }
1474
1475   pthread_cleanup_push (cl, NULL);
1476
1477   char mem[10];
1478   pread (tempfd, mem, sizeof (mem), 0);
1479
1480   pthread_cleanup_pop (0);
1481
1482   printf ("%s: pread returned\n", __FUNCTION__);
1483
1484   exit (1);
1485 }
1486
1487
1488 static void *
1489 tf_pwrite (void *arg)
1490 {
1491   if (arg == NULL)
1492     // XXX If somebody can provide a portable test case in which pwrite()
1493     // blocks we can enable this test to run in both rounds.
1494     abort ();
1495
1496   char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
1497   tempfd = mkstemp (fname);
1498   if (tempfd == -1)
1499     {
1500       printf ("%s: mkstemp failed\n", __FUNCTION__);
1501       exit (1);
1502     }
1503   unlink (fname);
1504
1505   int r = pthread_barrier_wait (&b2);
1506   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1507     {
1508       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1509       exit (1);
1510     }
1511
1512   r = pthread_barrier_wait (&b2);
1513   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1514     {
1515       printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1516       exit (1);
1517     }
1518
1519   pthread_cleanup_push (cl, NULL);
1520
1521   char mem[10];
1522   pwrite (tempfd, mem, sizeof (mem), 0);
1523
1524   pthread_cleanup_pop (0);
1525
1526   printf ("%s: pwrite returned\n", __FUNCTION__);
1527
1528   exit (1);
1529 }
1530
1531
1532 static void *
1533 tf_fsync (void *arg)
1534 {
1535   if (arg == NULL)
1536     // XXX If somebody can provide a portable test case in which fsync()
1537     // blocks we can enable this test to run in both rounds.
1538     abort ();
1539
1540   tempfd = open ("Makefile", O_RDONLY);
1541   if (tempfd == -1)
1542     {
1543       printf ("%s: cannot open Makefile\n", __FUNCTION__);
1544       exit (1);
1545     }
1546
1547   int r = pthread_barrier_wait (&b2);
1548   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1549     {
1550       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1551       exit (1);
1552     }
1553
1554   r = pthread_barrier_wait (&b2);
1555   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1556     {
1557       printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1558       exit (1);
1559     }
1560
1561   pthread_cleanup_push (cl, NULL);
1562
1563   fsync (tempfd);
1564
1565   pthread_cleanup_pop (0);
1566
1567   printf ("%s: fsync returned\n", __FUNCTION__);
1568
1569   exit (1);
1570 }
1571
1572
1573 static void *
1574 tf_fdatasync (void *arg)
1575 {
1576   if (arg == NULL)
1577     // XXX If somebody can provide a portable test case in which fdatasync()
1578     // blocks we can enable this test to run in both rounds.
1579     abort ();
1580
1581   tempfd = open ("Makefile", O_RDONLY);
1582   if (tempfd == -1)
1583     {
1584       printf ("%s: cannot open Makefile\n", __FUNCTION__);
1585       exit (1);
1586     }
1587
1588   int r = pthread_barrier_wait (&b2);
1589   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1590     {
1591       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1592       exit (1);
1593     }
1594
1595   r = pthread_barrier_wait (&b2);
1596   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1597     {
1598       printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1599       exit (1);
1600     }
1601
1602   pthread_cleanup_push (cl, NULL);
1603
1604   fdatasync (tempfd);
1605
1606   pthread_cleanup_pop (0);
1607
1608   printf ("%s: fdatasync returned\n", __FUNCTION__);
1609
1610   exit (1);
1611 }
1612
1613
1614 static void *
1615 tf_msync (void *arg)
1616 {
1617   if (arg == NULL)
1618     // XXX If somebody can provide a portable test case in which msync()
1619     // blocks we can enable this test to run in both rounds.
1620     abort ();
1621
1622   tempfd = open ("Makefile", O_RDONLY);
1623   if (tempfd == -1)
1624     {
1625       printf ("%s: cannot open Makefile\n", __FUNCTION__);
1626       exit (1);
1627     }
1628   void *p = mmap (NULL, 10, PROT_READ, MAP_SHARED, tempfd, 0);
1629   if (p == MAP_FAILED)
1630     {
1631       printf ("%s: mmap failed\n", __FUNCTION__);
1632       exit (1);
1633     }
1634
1635   int r = pthread_barrier_wait (&b2);
1636   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1637     {
1638       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1639       exit (1);
1640     }
1641
1642   r = pthread_barrier_wait (&b2);
1643   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1644     {
1645       printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1646       exit (1);
1647     }
1648
1649   pthread_cleanup_push (cl, NULL);
1650
1651   msync (p, 10, 0);
1652
1653   pthread_cleanup_pop (0);
1654
1655   printf ("%s: msync returned\n", __FUNCTION__);
1656
1657   exit (1);
1658 }
1659
1660
1661 static void *
1662 tf_sendto (void *arg)
1663 {
1664   if (arg == NULL)
1665     // XXX If somebody can provide a portable test case in which sendto()
1666     // blocks we can enable this test to run in both rounds.
1667     abort ();
1668
1669   struct sockaddr_un sun;
1670
1671   tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
1672   if (tempfd == -1)
1673     {
1674       printf ("%s: first socket call failed\n", __FUNCTION__);
1675       exit (1);
1676     }
1677
1678   int tries = 0;
1679   do
1680     {
1681       if (++tries > 10)
1682         {
1683           printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
1684         }
1685
1686       strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-6-XXXXXX");
1687       if (mktemp (sun.sun_path) == NULL)
1688         {
1689           printf ("%s: cannot generate temp file name\n", __FUNCTION__);
1690           exit (1);
1691         }
1692
1693       sun.sun_family = AF_UNIX;
1694     }
1695   while (bind (tempfd, (struct sockaddr *) &sun,
1696                offsetof (struct sockaddr_un, sun_path)
1697                + strlen (sun.sun_path) + 1) != 0);
1698   tempfname = strdup (sun.sun_path);
1699
1700   tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
1701   if (tempfd2 == -1)
1702     {
1703       printf ("%s: second socket call failed\n", __FUNCTION__);
1704       exit (1);
1705     }
1706
1707   int r = pthread_barrier_wait (&b2);
1708   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1709     {
1710       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1711       exit (1);
1712     }
1713
1714   r = pthread_barrier_wait (&b2);
1715   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1716     {
1717       printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1718       exit (1);
1719     }
1720
1721   pthread_cleanup_push (cl, NULL);
1722
1723   char mem[1];
1724
1725   sendto (tempfd2, mem, arg == NULL ? sizeof (mem) : 1, 0,
1726           (struct sockaddr *) &sun,
1727           offsetof (struct sockaddr_un, sun_path) + strlen (sun.sun_path) + 1);
1728
1729   pthread_cleanup_pop (0);
1730
1731   printf ("%s: sendto returned\n", __FUNCTION__);
1732
1733   exit (1);
1734 }
1735
1736
1737 static void *
1738 tf_sendmsg (void *arg)
1739 {
1740   if (arg == NULL)
1741     // XXX If somebody can provide a portable test case in which sendmsg()
1742     // blocks we can enable this test to run in both rounds.
1743     abort ();
1744
1745   struct sockaddr_un sun;
1746
1747   tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
1748   if (tempfd == -1)
1749     {
1750       printf ("%s: first socket call failed\n", __FUNCTION__);
1751       exit (1);
1752     }
1753
1754   int tries = 0;
1755   do
1756     {
1757       if (++tries > 10)
1758         {
1759           printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
1760         }
1761
1762       strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-7-XXXXXX");
1763       if (mktemp (sun.sun_path) == NULL)
1764         {
1765           printf ("%s: cannot generate temp file name\n", __FUNCTION__);
1766           exit (1);
1767         }
1768
1769       sun.sun_family = AF_UNIX;
1770     }
1771   while (bind (tempfd, (struct sockaddr *) &sun,
1772                offsetof (struct sockaddr_un, sun_path)
1773                + strlen (sun.sun_path) + 1) != 0);
1774   tempfname = strdup (sun.sun_path);
1775
1776   tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
1777   if (tempfd2 == -1)
1778     {
1779       printf ("%s: second socket call failed\n", __FUNCTION__);
1780       exit (1);
1781     }
1782
1783   int r = pthread_barrier_wait (&b2);
1784   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1785     {
1786       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1787       exit (1);
1788     }
1789
1790   r = pthread_barrier_wait (&b2);
1791   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1792     {
1793       printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1794       exit (1);
1795     }
1796
1797   pthread_cleanup_push (cl, NULL);
1798
1799   char mem[1];
1800   struct iovec iov[1];
1801   iov[0].iov_base = mem;
1802   iov[0].iov_len = 1;
1803
1804   struct msghdr m;
1805   m.msg_name = &sun;
1806   m.msg_namelen = (offsetof (struct sockaddr_un, sun_path)
1807                    + strlen (sun.sun_path) + 1);
1808   m.msg_iov = iov;
1809   m.msg_iovlen = 1;
1810   m.msg_control = NULL;
1811   m.msg_controllen = 0;
1812
1813   sendmsg (tempfd2, &m, 0);
1814
1815   pthread_cleanup_pop (0);
1816
1817   printf ("%s: sendmsg returned\n", __FUNCTION__);
1818
1819   exit (1);
1820 }
1821
1822
1823 static void *
1824 tf_creat (void *arg)
1825 {
1826   if (arg == NULL)
1827     // XXX If somebody can provide a portable test case in which sendmsg()
1828     // blocks we can enable this test to run in both rounds.
1829     abort ();
1830
1831   int r = pthread_barrier_wait (&b2);
1832   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1833     {
1834       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1835       exit (1);
1836     }
1837
1838   r = pthread_barrier_wait (&b2);
1839   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1840     {
1841       printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1842       exit (1);
1843     }
1844
1845   pthread_cleanup_push (cl, NULL);
1846
1847   creat ("tmp/tst-cancel-4-should-not-exist", 0666);
1848
1849   pthread_cleanup_pop (0);
1850
1851   printf ("%s: creat returned\n", __FUNCTION__);
1852
1853   exit (1);
1854 }
1855
1856
1857 static void *
1858 tf_connect (void *arg)
1859 {
1860   if (arg == NULL)
1861     // XXX If somebody can provide a portable test case in which connect()
1862     // blocks we can enable this test to run in both rounds.
1863     abort ();
1864
1865   struct sockaddr_un sun;
1866
1867   tempfd = socket (AF_UNIX, SOCK_STREAM, 0);
1868   if (tempfd == -1)
1869     {
1870       printf ("%s: first socket call failed\n", __FUNCTION__);
1871       exit (1);
1872     }
1873
1874   int tries = 0;
1875   do
1876     {
1877       if (++tries > 10)
1878         {
1879           printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
1880         }
1881
1882       strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-2-XXXXXX");
1883       if (mktemp (sun.sun_path) == NULL)
1884         {
1885           printf ("%s: cannot generate temp file name\n", __FUNCTION__);
1886           exit (1);
1887         }
1888
1889       sun.sun_family = AF_UNIX;
1890     }
1891   while (bind (tempfd, (struct sockaddr *) &sun,
1892                offsetof (struct sockaddr_un, sun_path)
1893                + strlen (sun.sun_path) + 1) != 0);
1894   tempfname = strdup (sun.sun_path);
1895
1896   listen (tempfd, 5);
1897
1898   tempfd2 = socket (AF_UNIX, SOCK_STREAM, 0);
1899   if (tempfd2 == -1)
1900     {
1901       printf ("%s: second socket call failed\n", __FUNCTION__);
1902       exit (1);
1903     }
1904
1905   int r = pthread_barrier_wait (&b2);
1906   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1907     {
1908       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1909       exit (1);
1910     }
1911
1912   if (arg != NULL)
1913     {
1914       r = pthread_barrier_wait (&b2);
1915       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1916         {
1917           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1918           exit (1);
1919         }
1920     }
1921
1922   pthread_cleanup_push (cl, NULL);
1923
1924   connect (tempfd2, (struct sockaddr *) &sun, sizeof (sun));
1925
1926   pthread_cleanup_pop (0);
1927
1928   printf ("%s: connect returned\n", __FUNCTION__);
1929
1930   exit (1);
1931 }
1932
1933
1934 static void *
1935 tf_tcdrain (void *arg)
1936 {
1937   if (arg == NULL)
1938     // XXX If somebody can provide a portable test case in which tcdrain()
1939     // blocks we can enable this test to run in both rounds.
1940     abort ();
1941
1942   int r = pthread_barrier_wait (&b2);
1943   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1944     {
1945       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1946       exit (1);
1947     }
1948
1949   if (arg != NULL)
1950     {
1951       r = pthread_barrier_wait (&b2);
1952       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1953         {
1954           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1955           exit (1);
1956         }
1957     }
1958
1959   pthread_cleanup_push (cl, NULL);
1960
1961   /* Regardless of stderr being a terminal, the tcdrain call should be
1962      canceled.  */
1963   tcdrain (STDERR_FILENO);
1964
1965   pthread_cleanup_pop (0);
1966
1967   printf ("%s: tcdrain returned\n", __FUNCTION__);
1968
1969   exit (1);
1970 }
1971
1972
1973 static void *
1974 tf_msgrcv (void *arg)
1975 {
1976   tempmsg = msgget (IPC_PRIVATE, 0666 | IPC_CREAT);
1977   if (tempmsg == -1)
1978     {
1979       printf ("%s: msgget failed: %s\n", __FUNCTION__, strerror (errno));
1980       exit (1);
1981     }
1982
1983   int r = pthread_barrier_wait (&b2);
1984   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1985     {
1986       printf ("%s: barrier_wait failed\n", __FUNCTION__);
1987       exit (1);
1988     }
1989
1990   if (arg != NULL)
1991     {
1992       r = pthread_barrier_wait (&b2);
1993       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
1994         {
1995           printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
1996           exit (1);
1997         }
1998     }
1999
2000   ssize_t s;
2001
2002   pthread_cleanup_push (cl, NULL);
2003
2004   struct
2005   {
2006     long int type;
2007     char mem[10];
2008   } m;
2009   int randnr;
2010   /* We need a positive random number.  */
2011   do
2012     randnr = random () % 64000;
2013   while (randnr <= 0);
2014   do
2015     {
2016       errno = 0;
2017       s = msgrcv (tempmsg, (struct msgbuf *) &m, 10, randnr, 0);
2018     }
2019   while (errno == EIDRM || errno == EINTR);
2020
2021   pthread_cleanup_pop (0);
2022
2023   printf ("%s: msgrcv returned %zd with errno = %m\n", __FUNCTION__, s);
2024
2025   msgctl (tempmsg, IPC_RMID, NULL);
2026
2027   exit (1);
2028 }
2029
2030
2031 static void *
2032 tf_msgsnd (void *arg)
2033 {
2034   if (arg == NULL)
2035     // XXX If somebody can provide a portable test case in which msgsnd()
2036     // blocks we can enable this test to run in both rounds.
2037     abort ();
2038
2039   tempmsg = msgget (IPC_PRIVATE, 0666 | IPC_CREAT);
2040   if (tempmsg == -1)
2041     {
2042       printf ("%s: msgget failed: %s\n", __FUNCTION__, strerror (errno));
2043       exit (1);
2044     }
2045
2046   int r = pthread_barrier_wait (&b2);
2047   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
2048     {
2049       printf ("%s: barrier_wait failed\n", __FUNCTION__);
2050       exit (1);
2051     }
2052
2053   r = pthread_barrier_wait (&b2);
2054   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
2055     {
2056       printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
2057       exit (1);
2058     }
2059
2060   pthread_cleanup_push (cl, NULL);
2061
2062   struct
2063   {
2064     long int type;
2065     char mem[1];
2066   } m;
2067   /* We need a positive random number.  */
2068   do
2069     m.type = random () % 64000;
2070   while (m.type <= 0);
2071   msgsnd (tempmsg, (struct msgbuf *) &m, sizeof (m.mem), 0);
2072
2073   pthread_cleanup_pop (0);
2074
2075   printf ("%s: msgsnd returned\n", __FUNCTION__);
2076
2077   msgctl (tempmsg, IPC_RMID, NULL);
2078
2079   exit (1);
2080 }
2081
2082
2083 static struct
2084 {
2085   const char *name;
2086   void *(*tf) (void *);
2087   int nb;
2088   int only_early;
2089 } tests[] =
2090 {
2091 #define ADD_TEST(name, nbar, early) { #name, tf_##name, nbar, early }
2092   ADD_TEST (read, 2, 0),
2093   ADD_TEST (readv, 2, 0),
2094   ADD_TEST (select, 2, 0),
2095   ADD_TEST (pselect, 2, 0),
2096   ADD_TEST (poll, 2, 0),
2097   ADD_TEST (ppoll, 2, 0),
2098   ADD_TEST (write, 2, 0),
2099   ADD_TEST (writev, 2, 0),
2100   ADD_TEST (sleep, 2, 0),
2101   ADD_TEST (usleep, 2, 0),
2102   ADD_TEST (nanosleep, 2, 0),
2103   ADD_TEST (wait, 2, 0),
2104   ADD_TEST (waitid, 2, 0),
2105   ADD_TEST (waitpid, 2, 0),
2106   ADD_TEST (sigpause, 2, 0),
2107   ADD_TEST (sigsuspend, 2, 0),
2108   ADD_TEST (sigwait, 2, 0),
2109   ADD_TEST (sigwaitinfo, 2, 0),
2110   ADD_TEST (sigtimedwait, 2, 0),
2111   ADD_TEST (pause, 2, 0),
2112   ADD_TEST (accept, 2, 0),
2113   ADD_TEST (send, 2, 0),
2114   ADD_TEST (recv, 2, 0),
2115   ADD_TEST (recvfrom, 2, 0),
2116   ADD_TEST (recvmsg, 2, 0),
2117   ADD_TEST (open, 2, 1),
2118   ADD_TEST (close, 2, 1),
2119   ADD_TEST (pread, 2, 1),
2120   ADD_TEST (pwrite, 2, 1),
2121   ADD_TEST (fsync, 2, 1),
2122   ADD_TEST (fdatasync, 2, 1),
2123   ADD_TEST (msync, 2, 1),
2124   ADD_TEST (sendto, 2, 1),
2125   ADD_TEST (sendmsg, 2, 1),
2126   ADD_TEST (creat, 2, 1),
2127   ADD_TEST (connect, 2, 1),
2128   ADD_TEST (tcdrain, 2, 1),
2129   ADD_TEST (msgrcv, 2, 0),
2130   ADD_TEST (msgsnd, 2, 1),
2131 };
2132 #define ntest_tf (sizeof (tests) / sizeof (tests[0]))
2133
2134
2135 static int
2136 do_test (void)
2137 {
2138   int val;
2139   socklen_t len;
2140
2141   if (socketpair (AF_UNIX, SOCK_STREAM, PF_UNIX, fds) != 0)
2142     {
2143       perror ("socketpair");
2144       exit (1);
2145     }
2146
2147   val = 1;
2148   len = sizeof(val);
2149   setsockopt (fds[1], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val));
2150   if (getsockopt (fds[1], SOL_SOCKET, SO_SNDBUF, &val, &len) < 0)
2151     {
2152       perror ("getsockopt");
2153       exit (1);
2154     }
2155   if (val >= WRITE_BUFFER_SIZE)
2156     {
2157       puts ("minimum write buffer size too large");
2158       exit (1);
2159     }
2160   setsockopt (fds[1], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val));
2161
2162   int result = 0;
2163   size_t cnt;
2164   for (cnt = 0; cnt < ntest_tf; ++cnt)
2165     {
2166       if (tests[cnt].only_early)
2167         continue;
2168
2169       if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
2170         {
2171           puts ("b2 init failed");
2172           exit (1);
2173         }
2174
2175       /* Reset the counter for the cleanup handler.  */
2176       cl_called = 0;
2177
2178       pthread_t th;
2179       if (pthread_create (&th, NULL, tests[cnt].tf, NULL) != 0)
2180         {
2181           printf ("create for '%s' test failed\n", tests[cnt].name);
2182           result = 1;
2183           continue;
2184         }
2185
2186       int r = pthread_barrier_wait (&b2);
2187       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
2188         {
2189           printf ("%s: barrier_wait failed\n", __FUNCTION__);
2190           result = 1;
2191           continue;
2192         }
2193
2194       struct timespec  ts = { .tv_sec = 0, .tv_nsec = 100000000 };
2195       while (nanosleep (&ts, &ts) != 0)
2196         continue;
2197
2198       if (pthread_cancel (th) != 0)
2199         {
2200           printf ("cancel for '%s' failed\n", tests[cnt].name);
2201           result = 1;
2202           continue;
2203         }
2204
2205       void *status;
2206       if (pthread_join (th, &status) != 0)
2207         {
2208           printf ("join for '%s' failed\n", tests[cnt].name);
2209           result = 1;
2210           continue;
2211         }
2212       if (status != PTHREAD_CANCELED)
2213         {
2214           printf ("thread for '%s' not canceled\n", tests[cnt].name);
2215           result = 1;
2216           continue;
2217         }
2218
2219       if (pthread_barrier_destroy (&b2) != 0)
2220         {
2221           puts ("barrier_destroy failed");
2222           result = 1;
2223           continue;
2224         }
2225
2226       if (cl_called == 0)
2227         {
2228           printf ("cleanup handler not called for '%s'\n", tests[cnt].name);
2229           result = 1;
2230           continue;
2231         }
2232       if (cl_called > 1)
2233         {
2234           printf ("cleanup handler called more than once for '%s'\n",
2235                   tests[cnt].name);
2236           result = 1;
2237           continue;
2238         }
2239
2240       printf ("in-time cancel test of '%s' successful\n", tests[cnt].name);
2241
2242       if (tempfd != -1)
2243         {
2244           close (tempfd);
2245           tempfd = -1;
2246         }
2247       if (tempfd2 != -1)
2248         {
2249           close (tempfd2);
2250           tempfd2 = -1;
2251         }
2252       if (tempfname != NULL)
2253         {
2254           unlink (tempfname);
2255           free (tempfname);
2256           tempfname = NULL;
2257         }
2258       if (tempmsg != -1)
2259         {
2260           msgctl (tempmsg, IPC_RMID, NULL);
2261           tempmsg = -1;
2262         }
2263     }
2264
2265   for (cnt = 0; cnt < ntest_tf; ++cnt)
2266     {
2267       if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
2268         {
2269           puts ("b2 init failed");
2270           exit (1);
2271         }
2272
2273       /* Reset the counter for the cleanup handler.  */
2274       cl_called = 0;
2275
2276       pthread_t th;
2277       if (pthread_create (&th, NULL, tests[cnt].tf, (void *) 1l) != 0)
2278         {
2279           printf ("create for '%s' test failed\n", tests[cnt].name);
2280           result = 1;
2281           continue;
2282         }
2283
2284       int r = pthread_barrier_wait (&b2);
2285       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
2286         {
2287           printf ("%s: barrier_wait failed\n", __FUNCTION__);
2288           result = 1;
2289           continue;
2290         }
2291
2292       if (pthread_cancel (th) != 0)
2293         {
2294           printf ("cancel for '%s' failed\n", tests[cnt].name);
2295           result = 1;
2296           continue;
2297         }
2298
2299       r = pthread_barrier_wait (&b2);
2300       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
2301         {
2302           printf ("%s: barrier_wait failed\n", __FUNCTION__);
2303           result = 1;
2304           continue;
2305         }
2306
2307       void *status;
2308       if (pthread_join (th, &status) != 0)
2309         {
2310           printf ("join for '%s' failed\n", tests[cnt].name);
2311           result = 1;
2312           continue;
2313         }
2314       if (status != PTHREAD_CANCELED)
2315         {
2316           printf ("thread for '%s' not canceled\n", tests[cnt].name);
2317           result = 1;
2318           continue;
2319         }
2320
2321       if (pthread_barrier_destroy (&b2) != 0)
2322         {
2323           puts ("barrier_destroy failed");
2324           result = 1;
2325           continue;
2326         }
2327
2328       if (cl_called == 0)
2329         {
2330           printf ("cleanup handler not called for '%s'\n", tests[cnt].name);
2331           result = 1;
2332           continue;
2333         }
2334       if (cl_called > 1)
2335         {
2336           printf ("cleanup handler called more than once for '%s'\n",
2337                   tests[cnt].name);
2338           result = 1;
2339           continue;
2340         }
2341
2342       printf ("early cancel test of '%s' successful\n", tests[cnt].name);
2343
2344       if (tempfd != -1)
2345         {
2346           close (tempfd);
2347           tempfd = -1;
2348         }
2349       if (tempfd2 != -1)
2350         {
2351           close (tempfd2);
2352           tempfd2 = -1;
2353         }
2354       if (tempfname != NULL)
2355         {
2356           unlink (tempfname);
2357           free (tempfname);
2358           tempfname = NULL;
2359         }
2360       if (tempmsg != -1)
2361         {
2362           msgctl (tempmsg, IPC_RMID, NULL);
2363           tempmsg = -1;
2364         }
2365     }
2366
2367   return result;
2368 }
2369
2370 #define TIMEOUT 60
2371 #define TEST_FUNCTION do_test ()
2372 #include "../test-skeleton.c"