master
c 2,723 lines 54.7 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 lxtlog.c
8
9 Abstract:
10
11 This file contains lx test logging routines.
12
13 --*/
14
15 #include "lxtutil.h"
16 #include "lxtlog.h"
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <unistd.h>
20 #include <errno.h>
21 #include <sched.h>
22 #include <linux/futex.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <sys/socket.h>
26 #include <sys/syscall.h>
27 #include <sys/stat.h>
28 #include <sys/mman.h>
29 #include <sys/utsname.h>
30 #include <fcntl.h>
31 #include <dirent.h>
32 #include <signal.h>
33
34 #define SIGNAL_WAIT_COUNT (20)
35 #define SIGNAL_WAIT_TIMEOUT_US (100000)
36 #define SIGNAL_MAX_SIGNALS (10)
37 #define SIGNAL_MAX_THREADS (5)
38
39 typedef struct _LXT_SIGNAL_INFO
40 {
41 pid_t ThreadId;
42 int ReceivedSignal[SIGNAL_MAX_SIGNALS];
43 siginfo_t SignalInfo[SIGNAL_MAX_SIGNALS];
44 BOOLEAN AllowMultipleSignals;
45 int SignalCount;
46 } LXT_SIGNAL_INFO, *PLXT_SIGNAL_INFO;
47
48 typedef struct _LXT_TYPE_MAPPING
49 {
50 char Type;
51 mode_t Mode;
52 } LXT_TYPE_MAPPING, *PLXT_TYPE_MAPPING;
53
54 void LxtPrintPartialMemory(const unsigned char* Buffer, size_t Size, size_t BufferIndex, const char* Prefix);
55
56 void LxtShowUsage(PCLXT_VARIATION Variations, unsigned int VariationCount);
57
58 PLXT_SIGNAL_INFO
59 LxtSignalFindThreadInfo(void);
60
61 void LxtSignalHandler(int Signal);
62
63 void LxtSignalHandlerSigAction(int Signal, siginfo_t* SigInfo, void* UContext);
64
65 //
66 // The multi-threaded signal tests require that information about the last
67 // signal received is stored per-thread, however using thread local storage
68 // is not safe in a signal handler (TLS support may take locks, if a signal
69 // arrives while the lock is held and the signal handler then tries to take
70 // the same lock, it leads to deadlock). Instead, an array is used that
71 // stores information for each thread.
72 //
73
74 static LXT_SIGNAL_INFO g_ThreadSignalInfo[SIGNAL_MAX_THREADS];
75 static int g_NextSignalThread = 0;
76 static LXT_TYPE_MAPPING g_TypeMapping[] = {
77 {DT_REG, S_IFREG}, {DT_DIR, S_IFDIR}, {DT_LNK, S_IFLNK}, {DT_FIFO, S_IFIFO}, {DT_SOCK, S_IFSOCK}, {DT_CHR, S_IFCHR}, {DT_BLK, S_IFBLK}};
78
79 static int g_WslVersion = 0;
80
81 //
82 // Test framework code
83 //
84
85 int LxtCheckDirectoryContents(const char* Path, const LXT_CHILD_INFO* Children, size_t Count)
86
87 /*++
88
89 Description:
90
91 This routine tests if the specified children are present in the directory.
92
93 Arguments:
94
95 Path - Supplies the path of the directory.
96
97 Children - Supplies the list of expected children.
98
99 Count - Supplies the number of children.
100
101 Return Value:
102
103 Returns 0 on success, -1 on failure.
104
105 --*/
106
107 {
108
109 return LxtCheckDirectoryContentsEx(Path, Children, Count, LXT_CHECK_DIRECTORY_CONTENTS_READ_FILES);
110 }
111
112 int LxtCheckDirectoryContentsEx(const char* Path, const LXT_CHILD_INFO* Children, size_t Count, int Flags)
113
114 /*++
115
116 Description:
117
118 This routine tests if the specified children are present in the directory.
119
120 Arguments:
121
122 Path - Supplies the path of the directory.
123
124 Children - Supplies the list of expected children.
125
126 Count - Supplies the number of children.
127
128 Flags - Supplies the flags.
129
130 Return Value:
131
132 Returns 0 on success, -1 on failure.
133
134 --*/
135
136 {
137
138 DIR* Directory;
139 struct dirent* Entry;
140 BOOLEAN* FoundEntries;
141 char FullPath[1024];
142 size_t Index;
143 int Result;
144 struct stat Stat;
145
146 FoundEntries = malloc(Count * sizeof(BOOLEAN));
147 memset(FoundEntries, 0, Count * sizeof(BOOLEAN));
148 Directory = opendir(Path);
149 if (Directory == NULL)
150 {
151 LxtLogError("opendir failed, errno: %d (%s)", errno, strerror(errno));
152 Result = LXT_RESULT_FAILURE;
153 goto ErrorExit;
154 }
155
156 errno = 0;
157 while ((Entry = readdir(Directory)) != NULL)
158 {
159 LxtLogInfo(
160 "Entry %p - d_name: %s d_ino: %llu d_type: %d d_off: %d d_reclen: %d",
161 Entry,
162 Entry->d_name,
163 Entry->d_ino,
164 Entry->d_type,
165 Entry->d_off,
166 Entry->d_reclen);
167
168 for (Index = 0; Index < Count; Index += 1)
169 {
170 if (strcmp(Children[Index].Name, Entry->d_name) == 0)
171 {
172 if (FoundEntries[Index] != FALSE)
173 {
174 LxtLogError("Duplicate entry '%s'", Entry->d_name);
175 Result = LXT_RESULT_FAILURE;
176 goto ErrorExit;
177 }
178
179 LxtCheckEqual(FoundEntries[Index], FALSE, "%d");
180 LxtCheckGreater(Entry->d_ino, 0, "%llu");
181 LxtCheckEqual(Entry->d_type, Children[Index].FileType, "%d");
182 FoundEntries[Index] = TRUE;
183 strcpy(FullPath, Path);
184 strcat(FullPath, "/");
185 strcat(FullPath, Entry->d_name);
186 LxtCheckResult(LxtCheckStat(FullPath, Entry->d_ino, Children[Index].FileType));
187
188 if ((Flags & LXT_CHECK_DIRECTORY_CONTENTS_READ_FILES) != 0)
189 {
190 LxtCheckResult(LxtCheckRead(FullPath, Children[Index].FileType));
191 }
192 }
193 }
194 }
195
196 if (errno != 0)
197 {
198 LxtLogError("readdir failed; errno: %d (%s)", errno, strerror(errno));
199 Result = LXT_RESULT_FAILURE;
200 goto ErrorExit;
201 }
202
203 //
204 // Check if all the required entries have been found.
205 //
206
207 for (Index = 0; Index < Count; Index += 1)
208 {
209 if (FoundEntries[Index] == FALSE)
210 {
211 LxtLogError("Entry '%s' is missing", Children[Index].Name);
212 Result = LXT_RESULT_FAILURE;
213 goto ErrorExit;
214 }
215 }
216
217 Result = LXT_RESULT_SUCCESS;
218
219 ErrorExit:
220 if (Directory != NULL)
221 {
222 closedir(Directory);
223 }
224
225 if (FoundEntries != NULL)
226 {
227 free(FoundEntries);
228 }
229
230 return Result;
231 }
232
233 int LxtCheckFdPath(int Fd, char* ExpectedPath)
234
235 /*++
236
237 Description:
238
239 This routine checks if the file descriptor has the specified path.
240
241 Arguments:
242
243 Fd - Supplies the file descriptor.
244
245 ExpectedPath - Supplies the expected path.
246
247 Return Value:
248
249 Returns 0 on success, -1 on failure.
250
251 --*/
252
253 {
254
255 char ProcFsPath[PATH_MAX];
256 char Path[PATH_MAX];
257 int Result;
258
259 sprintf(ProcFsPath, "/proc/self/fd/%d", Fd);
260 LxtCheckResult(LxtCheckLinkTarget(ProcFsPath, ExpectedPath));
261
262 ErrorExit:
263 return Result;
264 }
265
266 int LxtCheckLinkTarget(const char* Path, const char* ExpectedTarget)
267
268 /*++
269
270 Description:
271
272 This routine tests the target of the specified link.
273
274 Arguments:
275
276 Path - Supplies the path of the link.
277
278 ExpectedTarget - Supplies the expected target of the link.
279
280 Return Value:
281
282 Returns 0 on success, -1 on failure.
283
284 --*/
285
286 {
287
288 char Buffer[256] = {0};
289 int Result;
290 ssize_t Size;
291
292 LxtCheckErrno(Size = readlink(Path, Buffer, sizeof(Buffer)));
293 LxtCheckEqual((size_t)Size, strlen(Buffer), "%d");
294 LxtCheckStringEqual(ExpectedTarget, Buffer);
295
296 ErrorExit:
297 return Result;
298 }
299
300 int LxtCheckRead(const char* FullPath, unsigned char FileType)
301
302 /*++
303
304 Description:
305
306 This routine checks that the specified file can be read.
307
308 N.B. This only checks that the file can be opened and read, it doesn't
309 check if the contents match what's expected. Write additional tests
310 for a specific file if necessary.
311
312 Arguments:
313
314 FullPath - Supplies the full path of the file or directory.
315
316 FileType - Supplies the file type.
317
318 Return Value:
319
320 Returns 0 on success, -1 on failure.
321
322 --*/
323
324 {
325
326 char Buffer[1024];
327 int Fd;
328 int Result;
329 ssize_t Size;
330 struct stat Stat;
331
332 Fd = 0;
333 switch (FileType)
334 {
335 case DT_REG:
336
337 //
338 // Skip files that aren't readable.
339 //
340
341 LxtCheckErrnoZeroSuccess(lstat(FullPath, &Stat));
342 if ((Stat.st_mode & S_IRUSR) == 0)
343 {
344 Result = LXT_RESULT_SUCCESS;
345 goto ErrorExit;
346 }
347
348 LxtCheckErrno(Fd = open(FullPath, O_RDONLY));
349 LxtCheckErrno(Size = read(Fd, Buffer, sizeof(Buffer)));
350 LxtCheckGreater(Size, 0, "%d");
351 break;
352
353 case DT_LNK:
354 LxtCheckErrno(Size = readlink(FullPath, Buffer, sizeof(Buffer)));
355 LxtCheckGreater(Size, 0, "%d");
356 break;
357
358 case DT_DIR:
359
360 //
361 // Nothing to check.
362 //
363
364 Result = LXT_RESULT_SUCCESS;
365 break;
366
367 default:
368 LxtLogError("Unexpected file type %d", FileType);
369 Result = LXT_RESULT_FAILURE;
370 break;
371 }
372
373 ErrorExit:
374 if (Result < 0)
375 {
376 LxtLogError("Error reading %s", FullPath);
377 }
378
379 if (Fd > 0)
380 {
381 close(Fd);
382 }
383
384 return Result;
385 }
386
387 int LxtCheckStat(const char* FullPath, unsigned long long ExpectedInode, unsigned char FileType)
388
389 /*++
390
391 Description:
392
393 This routine checks the stat information for a file or directory.
394
395 Arguments:
396
397 FullPath - Supplies the full path of the file or directory.
398
399 ExpectedInode - Supplies the expected inode number.
400
401 FileType - Supplies the file type.
402
403 Return Value:
404
405 Returns 0 on success, -1 on failure.
406
407 --*/
408
409 {
410
411 int Index;
412 int Result;
413 struct stat Stat;
414
415 LxtCheckErrnoZeroSuccess(lstat(FullPath, &Stat));
416 LxtCheckEqual(Stat.st_ino, ExpectedInode, "%llu");
417 LxtCheckGreater(Stat.st_nlink, 0, "%ud");
418 for (Index = 0; Index < LXT_COUNT_OF(g_TypeMapping); Index += 1)
419 {
420 if (g_TypeMapping[Index].Type == FileType)
421 {
422 LxtCheckEqual((Stat.st_mode & S_IFMT), g_TypeMapping[Index].Mode, "0%o");
423
424 break;
425 }
426 }
427
428 if (Index == LXT_COUNT_OF(g_TypeMapping))
429 {
430 LxtLogError("Unexpected file type %d", FileType);
431 Result = LXT_RESULT_FAILURE;
432 goto ErrorExit;
433 }
434
435 ErrorExit:
436 return Result;
437 }
438
439 int LxtCheckWrite(const char* FullPath, const char* Value)
440
441 /*++
442
443 Description:
444
445 This routine checks that the specified file can be written to.
446
447 N.B. This function is meant for writable files in /proc and /sys. It's
448 primarily used for files that currently don't have a real write
449 implementation (which allow but silently ignore the write) since the
450 effects of the write are not checked.
451
452 Arguments:
453
454 FullPath - Supplies the full path of the file or directory.
455
456 FileType - Supplies the file type.
457
458 Return Value:
459
460 Returns 0 on success, -1 on failure.
461
462 --*/
463
464 {
465
466 ssize_t BytesWritten;
467 int Fd;
468 int Result;
469
470 LxtCheckErrno(Fd = open(FullPath, O_WRONLY));
471 LxtCheckErrno(BytesWritten = write(Fd, Value, strlen(Value)));
472 LxtCheckEqual((size_t)BytesWritten, strlen(Value), "%d");
473
474 ErrorExit:
475 if (Result < 0)
476 {
477 LxtLogError("Error writing %s", FullPath);
478 }
479
480 if (Fd > 0)
481 {
482 close(Fd);
483 }
484
485 return Result;
486 }
487
488 int LxtCheckWslPathTranslation(char* Path, const char* ExpectedPath, bool WinPath)
489
490 /*++
491
492 Description:
493
494 This routine checks whether translating a path with wslpath matches the
495 specified result. Pass NULL as ExpectedPath to assert that wslpath fails
496 to translate the path.
497
498 Arguments:
499
500 Path - Supplies the path to translate.
501
502 ExpectedPath - Supplies the expected translated path, or NULL to assert
503 that wslpath fails.
504
505 WinPath - Supplies a value that indicates whether the specified path is a
506 Windows path. When true, the expected path must be a Linux path and
507 vice versa.
508
509 Return Value:
510
511 Returns 0 on success, -1 on failure.
512
513 --*/
514
515 {
516
517 int Result;
518 char TranslatedPath[4096];
519
520 LxtCheckResult(LxtExecuteWslPath(Path, WinPath, TranslatedPath, sizeof(TranslatedPath), ExpectedPath == NULL ? 1 : 0));
521 if (ExpectedPath == NULL)
522 {
523 LxtLogInfo("%s => (failed as expected)", Path);
524 }
525 else
526 {
527 LxtCheckStringEqual(ExpectedPath, TranslatedPath);
528 LxtLogInfo("%s => %s", Path, TranslatedPath);
529 }
530
531 ErrorExit:
532 return Result;
533 }
534
535 int LxtExecuteAndReadOutput(char** Argv, char* OutputBuffer, size_t OutputBufferSize, int ExpectedExitCode)
536
537 /*++
538
539 Description:
540
541 This routine runs an executable, and reads stdout into the specified buffer.
542
543 N.B. If the process produces more output than fits in the buffer, this
544 function will fail.
545
546 Arguments:
547
548 Argv - Supplies the arguments to pass to the executable. The first element
549 is the executable to run.
550
551 OutputBuffer - Supplies the buffer to hold the process's stdout.
552
553 OutputBufferSize - Supplies the size of the output buffer.
554
555 ExpectedExitCode - Supplies the expected exit code of the child process.
556
557 Return Value:
558
559 Returns 0 on success, -1 on failure.
560
561 --*/
562
563 {
564
565 ssize_t BytesRead;
566 pid_t ChildPid;
567 int Result;
568 LXT_PIPE Pipe = {-1, -1};
569
570 LxtCheckResult(LxtCreatePipe(&Pipe));
571 LxtCheckErrno(ChildPid = fork());
572 if (ChildPid == 0)
573 {
574 LxtCheckClose(Pipe.Read);
575 LxtCheckErrno(dup2(Pipe.Write, STDOUT_FILENO));
576 LxtCheckClose(Pipe.Write);
577 LxtCheckErrno(execve(Argv[0], Argv, environ));
578 _exit(LXT_RESULT_FAILURE);
579 }
580
581 LxtCheckClose(Pipe.Write);
582 while ((BytesRead = read(Pipe.Read, OutputBuffer, OutputBufferSize)) > 0)
583 {
584 OutputBuffer += BytesRead;
585 OutputBufferSize -= BytesRead;
586 LxtCheckGreater(OutputBufferSize, 0, "%lu");
587 }
588
589 //
590 // Make sure the result did not exceed the buffer size and NULL-terminate
591 // it.
592 //
593
594 LxtCheckErrnoZeroSuccess(BytesRead);
595 LxtCheckGreater(OutputBufferSize, BytesRead, "%lu");
596 OutputBuffer[BytesRead] = '\0';
597
598 //
599 // Make sure the executable exited with the expected status.
600 //
601
602 LxtCheckResult(LxtWaitPidPoll(ChildPid, ExpectedExitCode << 8));
603
604 ErrorExit:
605 LxtClosePipe(&Pipe);
606
607 return Result;
608 }
609
610 int LxtExecuteWslPath(char* Path, bool WinPath, char* OutputBuffer, size_t OutputBufferSize, int ExpectedExitCode)
611
612 /*++
613
614 Description:
615
616 This routine runs wslpath, and reads stdout into the specified buffer.
617
618 N.B. If the process produces more output than fits in the buffer, this
619 function will fail.
620
621 Arguments:
622
623 Path - Supplies the path to translate.
624
625 WinPath - Supplies a value that indicates whether the specified path is a
626 Windows path. When true, the output will be a Linux path and vice versa.
627
628 OutputBuffer - Supplies the buffer to hold the process's stdout.
629
630 OutputBufferSize - Supplies the size of the output buffer.
631
632 ExpectedExitCode - Supplies the expected exit code of wslpath. Pass 1 when
633 the translation is expected to fail.
634
635 Return Value:
636
637 Returns 0 on success, -1 on failure.
638
639 --*/
640
641 {
642
643 char* Argv[4];
644 int Index = 0;
645 int Result;
646 size_t OutputLength;
647
648 //
649 // Construct the arguments to invoke wslpath.
650 //
651
652 Argv[Index++] = "/bin/wslpath";
653 if (WinPath == false)
654 {
655 Argv[Index++] = "-w";
656 }
657
658 Argv[Index++] = Path;
659 Argv[Index] = NULL;
660
661 //
662 // Execute wslpath.
663 //
664
665 LxtCheckResult(LxtExecuteAndReadOutput(Argv, OutputBuffer, OutputBufferSize, ExpectedExitCode));
666
667 //
668 // Wslpath outputs a new line at the end. Strip it to make things easier on
669 // the caller.
670 //
671
672 OutputLength = strlen(OutputBuffer);
673 if ((OutputLength > 0) && (OutputBuffer[OutputLength - 1] == '\n'))
674 {
675 OutputBuffer[OutputLength - 1] = '\0';
676 }
677
678 ErrorExit:
679 return Result;
680 }
681
682 int LxtInitialize(int Argc, char* Argv[], PLXT_ARGS Args, const char* TestName)
683
684 /*++
685 --*/
686
687 {
688
689 int Opt;
690 int OriginalOptErr;
691 int Result;
692
693 //
694 // Set umask to 0 so files created by tests have the expected permissions.
695 //
696
697 Result = umask(0);
698 if (Result < 0)
699 {
700 LxtLogError("umask failed %d", errno);
701 goto ErrorExit;
702 }
703
704 //
705 // Parse the command line, ignore unrecognized options since variations can
706 // specify their own options, and initialize logging.
707 //
708
709 Args->LogType = LXT_LOG_TYPE_DEFAULT_MASK;
710 Args->LogAppend = false;
711 Args->HelpRequested = false;
712 Args->VariationMask = -1;
713 Args->Argc = Argc;
714 Args->Argv = Argv;
715 OriginalOptErr = opterr;
716 opterr = 0;
717 while ((Opt = getopt(Argc, Argv, "l:v:a:h")) != LXT_RESULT_FAILURE)
718 {
719 switch (Opt)
720 {
721 case 'a':
722 Args->LogAppend = true;
723 break;
724
725 case 'l':
726 Args->LogType = atoi(optarg);
727 if (Args->LogType >= LxtLogTypeMax)
728 {
729 Result = LXT_RESULT_FAILURE;
730 LxtLogError("Invalid LxtLogType %d", Args->LogType);
731 goto ErrorExit;
732 }
733
734 break;
735
736 case 'v':
737 Args->VariationMask = atoll(optarg);
738 break;
739
740 case 'h':
741 Args->HelpRequested = true;
742 break;
743 }
744 }
745
746 opterr = OriginalOptErr;
747 Result = LxtLogInitialize(TestName, Args->LogType, Args->LogAppend);
748
749 ErrorExit:
750 return Result;
751 }
752
753 int LxtRunVariations(PLXT_ARGS Args, PCLXT_VARIATION Variations, unsigned int VariationCount)
754
755 /*++
756 --*/
757
758 {
759
760 unsigned int Itr;
761 unsigned long long ThisVariation;
762 int Result;
763
764 Result = LXT_RESULT_FAILURE;
765 if (Args->HelpRequested != false)
766 {
767 LxtShowUsage(Variations, VariationCount);
768 LxtLogError("No tests executed.");
769 goto ErrorExit;
770 }
771
772 for (Itr = 0; Itr < VariationCount; Itr++)
773 {
774 ThisVariation = (1ull << Itr);
775
776 //
777 // TODO: Currently, variation mask is only supported for the first 64
778 // variations.
779 //
780
781 if ((Args->VariationMask != 0) && ((ThisVariation & Args->VariationMask) == 0))
782 {
783
784 continue;
785 }
786
787 LxtLogStart("%s", Variations[Itr].Name);
788 Result = Variations[Itr].Variation(Args);
789 if (LXT_SUCCESS(Result) == 0)
790 {
791 LxtLogError("%s", Variations[Itr].Name);
792 goto ErrorExit;
793 }
794
795 LxtLogPassed("%s", Variations[Itr].Name);
796 }
797
798 ErrorExit:
799 return Result;
800 }
801
802 int LxtRunVariationsForked(PLXT_ARGS Args, PCLXT_VARIATION Variations, unsigned int VariationCount)
803
804 /*++
805
806 Routine Description:
807
808 This routine runs test variations, with each variation executing in its
809 own child process. Use this function if a test may change process state
810 that interferes with other tests.
811
812 Arguments:
813
814 Args - Supplies the command line arguments.
815
816 Variations - Supplies a pointer to an array of variations.
817
818 VariationCount - Supplies the number items in the variations array.
819
820 Return Value:
821
822 Returns 0 on success, -1 on failure.
823
824 --*/
825
826 {
827
828 int ChildPid;
829 unsigned int Itr;
830 unsigned long long ThisVariation;
831 int Result;
832
833 ChildPid = -1;
834 Result = LXT_RESULT_FAILURE;
835 if (Args->HelpRequested != false)
836 {
837 LxtShowUsage(Variations, VariationCount);
838 LxtLogError("No tests executed.");
839 goto ErrorExit;
840 }
841
842 for (Itr = 0; Itr < VariationCount; Itr++)
843 {
844 ThisVariation = (1ull << Itr);
845
846 //
847 // TODO: Currently, variation mask is only supported for the first 64
848 // variations.
849 //
850
851 if ((Args->VariationMask != 0) && ((ThisVariation & Args->VariationMask) == 0))
852 {
853
854 continue;
855 }
856
857 LxtCheckResult(ChildPid = fork());
858 if (ChildPid == 0)
859 {
860 LxtLogStart("%s", Variations[Itr].Name);
861 Result = Variations[Itr].Variation(Args);
862 if (LXT_SUCCESS(Result) == 0)
863 {
864 LxtLogError("%s", Variations[Itr].Name);
865 goto ErrorExit;
866 }
867
868 LxtLogPassed("%s", Variations[Itr].Name);
869 _exit(0);
870 }
871
872 Result = LxtWaitPidPollOptions(ChildPid, 0, 0, 120);
873 if (Result < 0)
874 {
875 LxtLogError("Test execution timed out.");
876 kill(ChildPid, SIGKILL);
877 Result = LXT_RESULT_FAILURE;
878 goto ErrorExit;
879 }
880 }
881
882 ErrorExit:
883 if (ChildPid == 0)
884 {
885 _exit(Result);
886 }
887
888 return Result;
889 }
890
891 void LxtUninitialize(void)
892
893 /*++
894 --*/
895
896 {
897
898 LxtLogUninitialize();
899 return;
900 }
901
902 //
903 // stdlib wrappers
904 //
905
906 void* LxtAlloc(size_t Size)
907
908 /*++
909 --*/
910
911 {
912
913 void* Allocation;
914
915 Allocation = malloc(Size);
916 if (Allocation == NULL)
917 {
918 LxtLogResourceError("malloc failed for size %d", Size);
919 }
920
921 return Allocation;
922 }
923
924 void LxtFree(void* Allocation)
925
926 /*++
927 --*/
928
929 {
930
931 free(Allocation);
932 return;
933 }
934
935 //
936 // syscall wrappers
937 //
938
939 #define LXT_WAITPID_WAIT_TIMEOUT_US 100000
940 #define LXT_MESSAGE_WAIT_TIMEOUT_US 100000
941 #define LXT_MESSAGE_WAIT_COUNT 20
942
943 int LxtClone(int (*Entry)(void* Parameter), void* Parameter, int Flags, PLXT_CLONE_ARGS Args)
944
945 /*++
946 --*/
947
948 {
949
950 char* ChildStack;
951 int Result;
952
953 Args->Stack = LxtAlloc(LXT_CLONE_STACK_SIZE);
954 if (Args->Stack == NULL)
955 {
956 Result = LXT_RESULT_FAILURE;
957 goto ErrorExit;
958 }
959
960 memset(Args->Stack, 0, LXT_CLONE_STACK_SIZE);
961 ChildStack = Args->Stack + LXT_CLONE_STACK_SIZE;
962 LxtCheckErrno(Args->CloneId = clone(Entry, ChildStack, Flags, Parameter, 0, 0, 0));
963
964 ErrorExit:
965 if (LXT_SUCCESS(Result) == 0)
966 {
967 LxtFree(Args->Stack);
968 Args->Stack = NULL;
969 }
970
971 return Result;
972 }
973
974 int LxtClosePipe(PLXT_PIPE Pipe)
975
976 /*++
977 --*/
978
979 {
980
981 int Result;
982
983 if (Pipe->Read != -1)
984 {
985 LxtCheckErrno(close(Pipe->Read));
986 Pipe->Read = -1;
987 }
988
989 if (Pipe->Write != -1)
990 {
991 LxtCheckErrno(close(Pipe->Write));
992 Pipe->Write = -1;
993 }
994
995 Result = 0;
996
997 ErrorExit:
998 return Result;
999 }
1000
1001 int LxtCompareMemory(const void* First, const void* Second, size_t Size, const char* FirstDescription, const char* SecondDescription)
1002
1003 /*++
1004
1005 Routine Description:
1006
1007 This routine compares two memory locations, and if they are different logs
1008 information about where they are different.
1009
1010 Arguments:
1011
1012 First - Supplies the address of the first memory location.
1013
1014 Second - Supplies the address of the second memory location.
1015
1016 Size - Supplies the size of the memory locations.
1017
1018 FirstDescription - Supplies the description of the first memory location.
1019
1020 SecondDescription - Supplies the description of the second memory location.
1021
1022 Return Value:
1023
1024 Returns 0 on success, -1 on failure.
1025
1026 --*/
1027
1028 {
1029
1030 size_t End;
1031 const unsigned char* FirstBytes;
1032 size_t DifferentIndex;
1033 size_t Index;
1034 int Result;
1035 const unsigned char* SecondBytes;
1036
1037 Result = LXT_RESULT_SUCCESS;
1038 FirstBytes = First;
1039 SecondBytes = Second;
1040 for (Index = 0; Index < Size; Index += 1)
1041 {
1042 if (FirstBytes[Index] != SecondBytes[Index])
1043 {
1044 Result = LXT_RESULT_FAILURE;
1045 break;
1046 }
1047 }
1048
1049 if (Result != LXT_RESULT_SUCCESS)
1050 {
1051 LxtLogError(
1052 "Memory contents of '%s' [1] differ from '%s' [2] at "
1053 "offset %ld",
1054 FirstDescription,
1055 SecondDescription,
1056 Index);
1057
1058 LxtPrintPartialMemory(FirstBytes, Size, Index, "[1]:");
1059 LxtPrintPartialMemory(SecondBytes, Size, Index, "[2]:");
1060 }
1061
1062 return Result;
1063 }
1064
1065 int LxtCopyFile(const char* Source, const char* Destination)
1066
1067 /*++
1068
1069 Description:
1070
1071 This routine copies a file.
1072
1073 Arguments:
1074
1075 Source - Supplies the source.
1076
1077 Destination - Supplies the destination.
1078
1079 Return Value:
1080
1081 Returns 0 on success, -1 on failure.
1082
1083 --*/
1084
1085 {
1086
1087 char Buffer[4096];
1088 ssize_t BytesRead;
1089 int FdDest;
1090 int FdSource;
1091 int Result;
1092 struct stat Stat;
1093
1094 FdDest = -1;
1095 FdSource = -1;
1096 LxtCheckErrno(FdSource = open(Source, O_RDONLY));
1097 LxtCheckErrnoZeroSuccess(fstat(FdSource, &Stat));
1098 LxtCheckErrno(FdDest = creat(Destination, Stat.st_mode & ~S_IFMT));
1099 do
1100 {
1101 LxtCheckErrno(BytesRead = read(FdSource, Buffer, sizeof(Buffer)));
1102 if (BytesRead > 0)
1103 {
1104 LxtCheckErrno(write(FdDest, Buffer, BytesRead));
1105 }
1106 } while (BytesRead > 0);
1107
1108 ErrorExit:
1109 if (FdDest >= 0)
1110 {
1111 close(FdDest);
1112 }
1113
1114 if (FdSource >= 0)
1115 {
1116 close(FdSource);
1117 }
1118
1119 return Result;
1120 }
1121
1122 int LxtCreatePipe(PLXT_PIPE Pipe)
1123
1124 /*++
1125 --*/
1126
1127 {
1128
1129 int Result;
1130
1131 memset(Pipe, -1, sizeof(*Pipe));
1132 LxtCheckErrno(pipe((int*)Pipe));
1133
1134 ErrorExit:
1135 return Result;
1136 }
1137
1138 int LxtJoinThread(pid_t* Tid)
1139
1140 {
1141
1142 pid_t CurrentTid;
1143
1144 while ((CurrentTid = *(volatile pid_t*)Tid) != 0)
1145 {
1146 if (syscall(SYS_futex, Tid, FUTEX_WAIT, CurrentTid, NULL, NULL, 0) < 0 && errno != EAGAIN)
1147 {
1148 return -1;
1149 }
1150 }
1151
1152 return 0;
1153 }
1154
1155 int LxtReceiveMessage(int Socket, const char* ExpectedMessage)
1156
1157 /*++
1158
1159 Routine Description:
1160
1161 This routine receives a message from a socket and checks if it was the
1162 expected message
1163
1164 Arguments:
1165
1166 Socket - Supplies a file descriptor for the socket to send on.
1167
1168 ExpectedMessage - Supplies a pointer to a zero-terminated string containing
1169 the expected message.
1170
1171 Return Value:
1172
1173 Returns 0 on success, -1 on failure.
1174
1175 --*/
1176
1177 {
1178
1179 int ExpectedMessageSize;
1180 char Message[100];
1181 int MessageSize;
1182 int Result;
1183 int WaitCount;
1184
1185 ExpectedMessageSize = strlen(ExpectedMessage);
1186 memset(Message, 0, sizeof(Message));
1187 for (WaitCount = 0; WaitCount < LXT_MESSAGE_WAIT_COUNT; WaitCount += 1)
1188 {
1189 MessageSize = recv(Socket, Message, sizeof(Message), MSG_DONTWAIT);
1190 if (MessageSize >= 0 || (errno != EAGAIN && errno != EWOULDBLOCK))
1191 {
1192 break;
1193 }
1194
1195 usleep(LXT_MESSAGE_WAIT_TIMEOUT_US);
1196 }
1197
1198 if (WaitCount == LXT_MESSAGE_WAIT_COUNT)
1199 {
1200 LxtLogError("Receiving the message timed out.");
1201 Result = LXT_RESULT_FAILURE;
1202 goto ErrorExit;
1203 }
1204
1205 LxtCheckErrno(MessageSize);
1206 if (MessageSize != ExpectedMessageSize)
1207 {
1208 LxtLogError("Received %i bytes, expected %i", MessageSize, ExpectedMessageSize);
1209
1210 Result = LXT_RESULT_FAILURE;
1211 goto ErrorExit;
1212 }
1213
1214 if (strncmp(Message, ExpectedMessage, ExpectedMessageSize) != 0)
1215 {
1216 LxtLogError("Received '%s', expected '%s'", Message, ExpectedMessage);
1217 Result = LXT_RESULT_FAILURE;
1218 goto ErrorExit;
1219 }
1220
1221 Result = LXT_RESULT_SUCCESS;
1222
1223 ErrorExit:
1224 return Result;
1225 }
1226
1227 void LxtPrintPartialMemory(const unsigned char* Buffer, size_t Size, size_t BufferIndex, const char* Prefix)
1228
1229 /*++
1230
1231 Routine Description:
1232
1233 This routine prints the contents of a memory buffer at the specified index
1234 with some context.
1235
1236 Arguments:
1237
1238 Buffer - Supplies the memory buffer to print.
1239
1240 Size - Supplies the size of the buffer.
1241
1242 BufferIndex - Supplies the index at which to print.
1243
1244 Prefix - Supplies the prefix for the message.
1245
1246 Return Value:
1247
1248 Returns 0 on success, -1 on failure.
1249
1250 --*/
1251
1252 {
1253
1254 size_t End;
1255 size_t Index;
1256 char Message[256];
1257 char Temp[10];
1258
1259 memset(Message, 0, sizeof(Message));
1260 Index = BufferIndex - 5;
1261 if (Index > BufferIndex)
1262 {
1263 Index = 0;
1264 }
1265
1266 End = Index + 11;
1267 if (End > Size)
1268 {
1269 End = Size;
1270 }
1271
1272 if (Prefix != NULL)
1273 {
1274 strcat(Message, Prefix);
1275 strcat(Message, " ");
1276 }
1277
1278 if (Index > 0)
1279 {
1280 strcat(Message, "...");
1281 }
1282
1283 for (; Index < End; Index += 1)
1284 {
1285 strcat(Message, " ");
1286 if (Index == BufferIndex)
1287 {
1288 strcat(Message, "(");
1289 }
1290
1291 sprintf(Temp, "%02x", Buffer[Index]);
1292 strcat(Message, Temp);
1293 if (Index == BufferIndex)
1294 {
1295 strcat(Message, ")");
1296 }
1297 }
1298
1299 if (End < Size)
1300 {
1301 strcat(Message, " ...");
1302 }
1303
1304 LxtLogInfo("%s", Message);
1305 return;
1306 }
1307
1308 int LxtSendMessage(int Socket, const char* Message)
1309
1310 /*++
1311
1312 Routine Description:
1313
1314 This routine sends a message to a socket and checks if it was successfully
1315 sent.
1316
1317 Arguments:
1318
1319 Socket - Supplies a file descriptor for the socket to send on.
1320
1321 Message - Supplies a pointer to a zero-terminated buffer containing the
1322 message.
1323
1324 Return Value:
1325
1326 Returns 0 on success, -1 on failure.
1327
1328 --*/
1329
1330 {
1331
1332 int MessageSize;
1333 int Result;
1334 int SentSize;
1335
1336 MessageSize = strlen(Message);
1337 LxtCheckErrno(SentSize = send(Socket, Message, MessageSize, 0));
1338 if (SentSize != MessageSize)
1339 {
1340 LxtLogError("Sent %i bytes, expected %i", SentSize, MessageSize);
1341 Result = LXT_RESULT_FAILURE;
1342 goto ErrorExit;
1343 }
1344
1345 Result = LXT_RESULT_SUCCESS;
1346
1347 ErrorExit:
1348 return Result;
1349 }
1350
1351 void LxtShowUsage(PCLXT_VARIATION Variations, unsigned int VariationCount)
1352
1353 /*++
1354
1355 Description:
1356
1357 This routine shows usage for the variations.
1358
1359 Arguments:
1360
1361 Variations - Supplies the variations.
1362
1363 VariationCount - Supplies the number of variations.
1364
1365 Return Value:
1366
1367 None.
1368
1369 --*/
1370
1371 {
1372
1373 size_t Index;
1374
1375 LxtLogInfo("Usage: ./test_name [-v <variation_mask>] [-l <log_type>] [-a] [-?]");
1376 LxtLogInfo("Variations:");
1377 for (Index = 0; Index < VariationCount; Index += 1)
1378 {
1379 LxtLogInfo("%s: %llu", Variations[Index].Name, 1ull << Index);
1380 }
1381
1382 return;
1383 }
1384
1385 int LxtSignalBlock(int Signal)
1386
1387 /*++
1388
1389 Routine Description:
1390
1391 This routine blocks the specified signal.
1392
1393 Arguments:
1394
1395 Signal - Supplies the signal number.
1396
1397 Return Value:
1398
1399 Returns 0 on success, -1 on failure.
1400
1401 --*/
1402
1403 {
1404
1405 int Result;
1406 sigset_t Signals;
1407
1408 sigemptyset(&Signals);
1409 sigaddset(&Signals, Signal);
1410 LxtCheckErrnoZeroSuccess(sigprocmask(SIG_BLOCK, &Signals, NULL));
1411
1412 ErrorExit:
1413 return Result;
1414 }
1415
1416 int LxtSignalDefault(int Signal)
1417
1418 /*++
1419
1420 Routine Description:
1421
1422 This routine reverts to the default action for the specified signal.
1423
1424 Arguments:
1425
1426 Signal - Supplies the signal number.
1427
1428 Return Value:
1429
1430 Returns 0 on success, -1 on failure.
1431
1432 --*/
1433
1434 {
1435
1436 struct sigaction Action;
1437 int Result;
1438
1439 memset(&Action, 0, sizeof(Action));
1440 Action.sa_handler = SIG_DFL;
1441 LxtCheckErrnoZeroSuccess(sigaction(Signal, &Action, NULL));
1442
1443 ErrorExit:
1444 return Result;
1445 }
1446
1447 int LxtSignalIgnore(int Signal)
1448
1449 /*++
1450
1451 Routine Description:
1452
1453 This routine ignores the specified signal.
1454
1455 Arguments:
1456
1457 Signal - Supplies the signal number.
1458
1459 Return Value:
1460
1461 Returns 0 on success, -1 on failure.
1462
1463 --*/
1464
1465 {
1466
1467 struct sigaction Action;
1468 int Result;
1469
1470 memset(&Action, 0, sizeof(Action));
1471 Action.sa_handler = SIG_IGN;
1472 LxtCheckErrnoZeroSuccess(sigaction(Signal, &Action, NULL));
1473
1474 ErrorExit:
1475 return Result;
1476 }
1477
1478 int LxtSignalCheckInfoReceived(int Signal, int Code, pid_t Pid, uid_t Uid)
1479
1480 /*++
1481
1482 Routine Description:
1483
1484 This routine checks if the specified signal was received by the signal
1485 handlers, with the specified info values.
1486
1487 N.B. The signal handler must have been established with SA_SIGINFO for this
1488 to work.
1489
1490 Arguments:
1491
1492 Signal - Supplies the expected signal number.
1493
1494 Code - Supplies the expected signal code.
1495
1496 Pid - Supplies the expected process ID.
1497
1498 Uid - Supplies the expected user ID.
1499
1500 Return Value:
1501
1502 Returns the index in the received signals array on success, -1 on failure.
1503
1504 --*/
1505
1506 {
1507
1508 int Index;
1509 PLXT_SIGNAL_INFO Info;
1510 int Result;
1511
1512 Info = LxtSignalFindThreadInfo();
1513 if (Info == NULL)
1514 {
1515 Result = LXT_RESULT_FAILURE;
1516 goto ErrorExit;
1517 }
1518
1519 LxtCheckResult(Index = LxtSignalCheckReceived(Signal));
1520 LxtCheckEqual(Signal, Info->SignalInfo[Index].si_signo, "%d");
1521 LxtCheckEqual(Code, Info->SignalInfo[Index].si_code, "%d");
1522 LxtCheckEqual(Pid, Info->SignalInfo[Index].si_pid, "%d");
1523 LxtCheckEqual(Uid, Info->SignalInfo[Index].si_uid, "%d");
1524 Result = Index;
1525
1526 ErrorExit:
1527 return Result;
1528 }
1529
1530 int LxtSignalCheckNoSignal(void)
1531
1532 /*++
1533
1534 Routine Description:
1535
1536 This routine checks if no signal was received.
1537
1538 Arguments:
1539
1540 None.
1541
1542 Return Value:
1543
1544 Returns 0 on success, -1 on failure.
1545
1546 --*/
1547
1548 {
1549
1550 PLXT_SIGNAL_INFO Info;
1551 int Result;
1552
1553 Info = LxtSignalFindThreadInfo();
1554 if (Info == NULL)
1555 {
1556 Result = LXT_RESULT_FAILURE;
1557 goto ErrorExit;
1558 }
1559
1560 if (Info->SignalCount == 0)
1561 {
1562 Result = LXT_RESULT_SUCCESS;
1563 }
1564 else
1565 {
1566 Result = LXT_RESULT_FAILURE;
1567 LxtLogError("Unexpected signal.");
1568 }
1569
1570 ErrorExit:
1571 return Result;
1572 }
1573
1574 int LxtSignalCheckReceived(int Signal)
1575
1576 /*++
1577
1578 Routine Description:
1579
1580 This routine checks if the specified signal was received by the signal
1581 handler.
1582
1583 Arguments:
1584
1585 Signal - Supplies the expected signal number.
1586
1587 Return Value:
1588
1589 Returns the index in the received signals array on success, -1 on failure.
1590
1591 --*/
1592
1593 {
1594
1595 int Index;
1596 PLXT_SIGNAL_INFO Info;
1597 int Result;
1598
1599 Info = LxtSignalFindThreadInfo();
1600 if (Info == NULL)
1601 {
1602 Result = LXT_RESULT_FAILURE;
1603 goto SignalCheckReceivedEnd;
1604 }
1605
1606 if (Info->SignalCount == 0)
1607 {
1608 Result = LXT_RESULT_FAILURE;
1609 LxtLogError("Signal %d was not received.", Signal);
1610 goto SignalCheckReceivedEnd;
1611 }
1612
1613 for (Index = 0; Index < Info->SignalCount; Index += 1)
1614 {
1615 if (Info->ReceivedSignal[Index] == -1)
1616 {
1617 Result = LXT_RESULT_FAILURE;
1618 LxtLogError("An error occurred in the signal handler");
1619 goto SignalCheckReceivedEnd;
1620 }
1621
1622 if (Info->ReceivedSignal[Index] == Signal)
1623 {
1624 Result = Index;
1625 goto SignalCheckReceivedEnd;
1626 }
1627 }
1628
1629 Result = LXT_RESULT_FAILURE;
1630 LxtLogError("Signal %d was not received!", Signal);
1631
1632 SignalCheckReceivedEnd:
1633 return Result;
1634 }
1635
1636 int LxtSignalCheckSigChldReceived(int Code, pid_t Pid, uid_t Uid, int Status)
1637
1638 /*++
1639
1640 Routine Description:
1641
1642 This routine checks if the SIGCHLD signal was received by the signal
1643 handlers, with the specified info values.
1644
1645 N.B. The signal handler must have been established with SA_SIGINFO for this
1646 to work.
1647
1648 Arguments:
1649
1650 Code - Supplies the expected signal code.
1651
1652 Pid - Supplies the expected process ID.
1653
1654 Uid - Supplies the expected user ID.
1655
1656 Status - Supplies the expected process status.
1657
1658 Return Value:
1659
1660 Returns the index in the received signals array on success, -1 on failure.
1661
1662 --*/
1663
1664 {
1665
1666 int Index;
1667 PLXT_SIGNAL_INFO Info;
1668 int Result;
1669
1670 Info = LxtSignalFindThreadInfo();
1671 if (Info == NULL)
1672 {
1673 Result = LXT_RESULT_FAILURE;
1674 goto ErrorExit;
1675 }
1676
1677 LxtCheckResult(Index = LxtSignalCheckInfoReceived(SIGCHLD, Code, Pid, Uid));
1678 LxtCheckEqual(Status, Info->SignalInfo[Index].si_status, "%d");
1679 Result = Index;
1680
1681 ErrorExit:
1682 return Result;
1683 }
1684
1685 PLXT_SIGNAL_INFO
1686 LxtSignalFindThreadInfo(void)
1687
1688 /*++
1689
1690 Description:
1691
1692 This routine finds the signal test info for the current thread.
1693
1694 Arguments:
1695
1696 None.
1697
1698 Return Value:
1699
1700 A pointer to the signal info, or NULL if the signal info was not
1701 initialized.
1702
1703 --*/
1704
1705 {
1706
1707 size_t Index;
1708 PLXT_SIGNAL_INFO Result;
1709 pid_t ThreadId;
1710
1711 Result = NULL;
1712 ThreadId = gettid();
1713 for (Index = 0; Index < SIGNAL_MAX_THREADS; Index += 1)
1714 {
1715 if (g_ThreadSignalInfo[Index].ThreadId == ThreadId)
1716 {
1717 Result = &g_ThreadSignalInfo[Index];
1718 break;
1719 }
1720 }
1721
1722 if (Result == NULL)
1723 {
1724 LxtLogError("LxtSignalInitializeThread not called for this thread.");
1725 goto ErrorExit;
1726 }
1727
1728 ErrorExit:
1729 return Result;
1730 }
1731
1732 int LxtSignalGetCount(void)
1733
1734 /*++
1735
1736 Routine Description:
1737
1738 This routine returns the number of received signals.
1739
1740 Arguments:
1741
1742 None.
1743
1744 Return Value:
1745
1746 The number of received signals, or -1 on failure.
1747
1748 --*/
1749
1750 {
1751
1752 PLXT_SIGNAL_INFO Info;
1753 int Result;
1754
1755 Info = LxtSignalFindThreadInfo();
1756 if (Info == NULL)
1757 {
1758 Result = LXT_RESULT_FAILURE;
1759 goto ErrorExit;
1760 }
1761
1762 Result = Info->SignalCount;
1763
1764 ErrorExit:
1765 return Result;
1766 }
1767
1768 int LxtSignalGetInfo(siginfo_t* SignalInfo)
1769
1770 /*++
1771
1772 Routine Description:
1773
1774 This routine gets a copy of the last received signal info.
1775
1776 Arguments:
1777
1778 SignalInfo - Supplies a pointer which receives the signal info.
1779
1780 Return Value:
1781
1782 Returns 0 on success, -1 on failure.
1783
1784 --*/
1785
1786 {
1787
1788 PLXT_SIGNAL_INFO Info;
1789 int Result;
1790
1791 Info = LxtSignalFindThreadInfo();
1792 if (Info == NULL)
1793 {
1794 Result = LXT_RESULT_FAILURE;
1795 goto ErrorExit;
1796 }
1797
1798 *SignalInfo = Info->SignalInfo[0];
1799 Result = LXT_RESULT_SUCCESS;
1800
1801 ErrorExit:
1802 return Result;
1803 }
1804
1805 void LxtSignalHandler(int Signal)
1806
1807 /*++
1808
1809 Routine Description:
1810
1811 This routine handles signals for the process.
1812
1813 Arguments:
1814
1815 Signal - Supplies the signal that was received
1816
1817 Return Value:
1818
1819 None.
1820
1821 --*/
1822
1823 {
1824
1825 int AllowedSignals;
1826 PLXT_SIGNAL_INFO Info;
1827 int Result;
1828
1829 Info = NULL;
1830
1831 #if defined(__i386__)
1832
1833 register int Eax asm("eax");
1834 register void* Ecx asm("ecx");
1835 register void* Edx asm("edx");
1836
1837 //
1838 // Verify register contents.
1839 //
1840
1841 LxtCheckEqual(Eax, Signal, "%d");
1842 LxtCheckEqual(Edx, NULL, "%p");
1843 LxtCheckEqual(Ecx, NULL, "%p");
1844
1845 //
1846 // Verify stack alignment.
1847 //
1848
1849 LxtCheckEqual((uintptr_t)&Signal & 0xf, 0, "%p");
1850
1851 #endif
1852
1853 Info = LxtSignalFindThreadInfo();
1854 if (Info == NULL)
1855 {
1856 Result = LXT_RESULT_FAILURE;
1857 goto ErrorExit;
1858 }
1859
1860 if (Info->AllowMultipleSignals != FALSE)
1861 {
1862 AllowedSignals = SIGNAL_MAX_SIGNALS;
1863 }
1864 else
1865 {
1866 AllowedSignals = 1;
1867 }
1868
1869 if (Info->SignalCount < AllowedSignals)
1870 {
1871 LxtLogInfo("Process %d got signal %d (%s)", getpid(), Signal, strsignal(Signal));
1872
1873 Result = Signal;
1874 }
1875 else
1876 {
1877 LxtLogError("Unexpected signal %d (%s)", Signal, strsignal(Signal));
1878 Result = LXT_RESULT_FAILURE;
1879 }
1880
1881 ErrorExit:
1882 if (Info != NULL)
1883 {
1884 if (Result < 0)
1885 {
1886 Info->ReceivedSignal[0] = LXT_RESULT_FAILURE;
1887 Info->SignalCount = 1;
1888 }
1889 else if (Info->SignalCount < AllowedSignals)
1890 {
1891 Info->ReceivedSignal[Info->SignalCount] = Result;
1892 Info->SignalCount += 1;
1893 }
1894 }
1895
1896 return;
1897 }
1898
1899 void LxtSignalHandlerSigAction(int Signal, siginfo_t* SigInfo, void* UContext)
1900
1901 /*++
1902
1903 Routine Description:
1904
1905 This routine handles signals for the process using the SA_SIGINFO flag.
1906
1907 Arguments:
1908
1909 Signal - Supplies the signal that was received.
1910
1911 SigInfo - Supplies additional information about the signal.
1912
1913 UContext - Supplies the scheduling context from the process before the
1914 signal handler was invoked.
1915
1916 Return Value:
1917
1918 None.
1919
1920 --*/
1921
1922 {
1923
1924 int AllowedSignals;
1925 PLXT_SIGNAL_INFO Info;
1926 int Result;
1927
1928 Info = NULL;
1929
1930 #if defined(__i386__)
1931
1932 register int Eax asm("eax");
1933 register void* Ecx asm("ecx");
1934 register void* Edx asm("edx");
1935
1936 //
1937 // Verify register contents.
1938 //
1939
1940 LxtCheckEqual(Eax, Signal, "%d");
1941 LxtCheckEqual(Edx, SigInfo, "%p");
1942 LxtCheckEqual(Ecx, UContext, "%p");
1943
1944 //
1945 // Verify stack alignment.
1946 //
1947
1948 LxtCheckEqual((uintptr_t)&Signal & 0xf, 0, "%p");
1949
1950 #endif
1951
1952 LxtCheckEqual(Signal, SigInfo->si_signo, "%d");
1953 Info = LxtSignalFindThreadInfo();
1954 if (Info == NULL)
1955 {
1956 Result = LXT_RESULT_FAILURE;
1957 goto ErrorExit;
1958 }
1959
1960 if (Info->AllowMultipleSignals != FALSE)
1961 {
1962 AllowedSignals = SIGNAL_MAX_SIGNALS;
1963 }
1964 else
1965 {
1966 AllowedSignals = 1;
1967 }
1968
1969 if (Info->SignalCount < AllowedSignals)
1970 {
1971 if (Signal == SIGCHLD)
1972 {
1973 LxtLogInfo(
1974 "Process %d(%d) got signal %d (%s), code %d, pid %d, "
1975 "uid %d, status %d",
1976 getpid(),
1977 gettid(),
1978 SigInfo->si_signo,
1979 strsignal(SigInfo->si_signo),
1980 SigInfo->si_code,
1981 SigInfo->si_pid,
1982 SigInfo->si_uid,
1983 SigInfo->si_status);
1984 }
1985 else
1986 {
1987 LxtLogInfo(
1988 "Process %d(%d) got signal %d (%s), code %d, pid %d, uid %d",
1989 getpid(),
1990 gettid(),
1991 SigInfo->si_signo,
1992 strsignal(SigInfo->si_signo),
1993 SigInfo->si_code,
1994 SigInfo->si_pid,
1995 SigInfo->si_uid);
1996 }
1997
1998 Result = Signal;
1999 }
2000 else
2001 {
2002 LxtLogError(
2003 "Process %d got unexpected signal %d (%s), code %d, pid %d, uid %d",
2004 getpid(),
2005 SigInfo->si_signo,
2006 strsignal(SigInfo->si_signo),
2007 SigInfo->si_code,
2008 SigInfo->si_pid,
2009 SigInfo->si_uid);
2010
2011 Result = LXT_RESULT_FAILURE;
2012 }
2013
2014 ErrorExit:
2015 if (Info != NULL)
2016 {
2017 if (Result < 0)
2018 {
2019 Info->ReceivedSignal[0] = LXT_RESULT_FAILURE;
2020 Info->SignalCount = 1;
2021 }
2022 else if (Info->SignalCount < AllowedSignals)
2023 {
2024 Info->ReceivedSignal[Info->SignalCount] = Result;
2025 Info->SignalInfo[Info->SignalCount] = *SigInfo;
2026 Info->SignalCount += 1;
2027 }
2028 }
2029
2030 return;
2031 }
2032
2033 int LxtSignalInitialize(void)
2034
2035 /*++
2036
2037 Description:
2038
2039 This routine initializes the signal test infrastructure for the current
2040 process.
2041
2042 N.B. Run this function for any process that uses the signal test
2043 infrastructure. If a test uses fork(), you must run this function
2044 again in the child process.
2045
2046 Arguments:
2047
2048 None.
2049
2050 Return Value:
2051
2052 Returns 0 on success, -1 on failure.
2053
2054 --*/
2055
2056 {
2057
2058 int Result;
2059
2060 g_NextSignalThread = 0;
2061 memset(g_ThreadSignalInfo, 0, sizeof(g_ThreadSignalInfo));
2062 return LxtSignalInitializeThread();
2063 }
2064
2065 int LxtSignalInitializeThread(void)
2066
2067 /*++
2068
2069 Description:
2070
2071 This routine initializes the signal test infrastructure for the current
2072 thread.
2073
2074 N.B. Run this function for any thread that uses the signal test
2075 infrastructure, except the main thread of the process; for the main
2076 thread, run LxtSignalInitialize instead.
2077
2078 Arguments:
2079
2080 None.
2081
2082 Return Value:
2083
2084 Returns 0 on success, -1 on failure.
2085
2086 --*/
2087
2088 {
2089
2090 int Index;
2091 int Result;
2092
2093 Index = __sync_fetch_and_add(&g_NextSignalThread, 1);
2094 if (Index >= SIGNAL_MAX_THREADS)
2095 {
2096 LxtLogError("Too many threads in signal test.");
2097 Result = LXT_RESULT_FAILURE;
2098 goto ErrorExit;
2099 }
2100
2101 if (g_ThreadSignalInfo[Index].ThreadId != 0)
2102 {
2103 LxtLogError("Invalid signal test state.");
2104 Result = LXT_RESULT_FAILURE;
2105 goto ErrorExit;
2106 }
2107
2108 g_ThreadSignalInfo[Index].ThreadId = gettid();
2109 Result = LXT_RESULT_SUCCESS;
2110
2111 ErrorExit:
2112 return Result;
2113 }
2114
2115 void LxtSignalResetReceived(void)
2116
2117 /*++
2118
2119 Routine Description:
2120
2121 This routine resets the global variables used by the signal handlers.
2122
2123 Arguments:
2124
2125 None.
2126
2127 Return Value:
2128
2129 None.
2130
2131 --*/
2132
2133 {
2134
2135 PLXT_SIGNAL_INFO Info;
2136
2137 Info = LxtSignalFindThreadInfo();
2138 if (Info == NULL)
2139 {
2140 goto ErrorExit;
2141 }
2142
2143 Info->SignalCount = 0;
2144
2145 ErrorExit:
2146 return;
2147 }
2148
2149 int LxtSignalSetupHandler(int Signal, int Flags)
2150
2151 /*++
2152
2153 Routine Description:
2154
2155 This routine sets up a signal handler.
2156
2157 Arguments:
2158
2159 Signal - Supplies the signal.
2160
2161 Flags - Supplies the flags.
2162
2163 Return Value:
2164
2165 0 on success, -1 on failure.
2166
2167 --*/
2168
2169 {
2170
2171 struct sigaction Action;
2172 int Result;
2173
2174 //
2175 // Check that the signal infrastructure was initialized properly.
2176 //
2177
2178 if (LxtSignalFindThreadInfo() == NULL)
2179 {
2180 Result = LXT_RESULT_FAILURE;
2181 goto ErrorExit;
2182 }
2183
2184 memset(&Action, 0, sizeof(Action));
2185 if ((Flags & SA_SIGINFO) != 0)
2186 {
2187 Action.sa_sigaction = LxtSignalHandlerSigAction;
2188 }
2189 else
2190 {
2191 Action.sa_handler = LxtSignalHandler;
2192 }
2193
2194 Action.sa_flags = Flags;
2195 LxtCheckErrnoZeroSuccess(sigaction(Signal, &Action, NULL));
2196
2197 ErrorExit:
2198 return Result;
2199 }
2200
2201 void LxtSignalSetAllowMultiple(BOOLEAN AllowMultiple)
2202
2203 /*++
2204
2205 Routine Description:
2206
2207 This routine sets whether or not receiving another signal when one was
2208 already received should be not considered an error.
2209
2210 Arguments:
2211
2212 AllowMultiple - Supplies a value that indicates whether multiple signals
2213 are allowed.
2214
2215 Return Value:
2216
2217 None.
2218
2219 --*/
2220
2221 {
2222
2223 PLXT_SIGNAL_INFO Info;
2224
2225 Info = LxtSignalFindThreadInfo();
2226 if (Info == NULL)
2227 {
2228 goto ErrorExit;
2229 }
2230
2231 Info->AllowMultipleSignals = AllowMultiple;
2232
2233 ErrorExit:
2234 return;
2235 }
2236
2237 int LxtSignalTimedWait(sigset_t* Set, siginfo_t* SignalInfo, struct timespec* Timeout)
2238
2239 /*++
2240
2241 Routine Description:
2242
2243 This routine calls the rt_sigtimedwait system call.
2244
2245 N.B. In glibc, the sigtimedwait function is available as a wrapper for
2246 this system call, but in bionic only sigwait is available which
2247 prevents access to some of the parameters of rt_sigtimedwait.
2248 Even in glibc the sigtimedwait wrapper should not be used for testing
2249 since it silently converts SI_TKILL to SI_USER.
2250
2251 Arguments:
2252
2253 Set - Supplies a pointer to the set of signals to wait for.
2254
2255 SignalInfo - Supplies a pointer that receives information about the signal.
2256
2257 Timeout - Supplies a pointer to a timeout value.
2258
2259 Return Value:
2260
2261 The signal number on success, -1 on failure with errno set appropriately.
2262
2263 --*/
2264
2265 {
2266
2267 #if defined(__GLIBC__)
2268 sigset_t* SignalSetPointer;
2269
2270 SignalSetPointer = Set;
2271 #else
2272 kernel_sigset_t SignalSet;
2273 kernel_sigset_t* SignalSetPointer;
2274
2275 //
2276 // Convert to the 64-bit signal set size that the kernel expects.
2277 //
2278
2279 SignalSetPointer = NULL;
2280 if (Set != NULL)
2281 {
2282 SignalSet = *Set;
2283 SignalSetPointer = &SignalSet;
2284 }
2285
2286 #endif
2287
2288 return syscall(SYS_rt_sigtimedwait, SignalSetPointer, SignalInfo, Timeout, _NSIG / 8);
2289 }
2290
2291 int LxtSignalUnblock(int Signal)
2292
2293 /*++
2294
2295 Routine Description:
2296
2297 This routine unblocks the specified signal.
2298
2299 Arguments:
2300
2301 Signal - Supplies the signal number.
2302
2303 Return Value:
2304
2305 Returns 0 on success, -1 on failure.
2306
2307 --*/
2308
2309 {
2310
2311 int Result;
2312 sigset_t Signals;
2313
2314 sigemptyset(&Signals);
2315 sigaddset(&Signals, Signal);
2316 LxtCheckErrnoZeroSuccess(sigprocmask(SIG_UNBLOCK, &Signals, NULL));
2317
2318 ErrorExit:
2319 return Result;
2320 }
2321
2322 void LxtSignalWait(void)
2323
2324 /*++
2325
2326 Routine Description:
2327
2328 This routine waits until a signal has been received, or a timeout expires.
2329
2330 N.B. This function does not return status to indicate whether a signal was
2331 received or not. Use the signal check functions after this
2332 function returns.
2333
2334 Arguments:
2335
2336 None.
2337
2338 Return Value:
2339
2340 None.
2341
2342 --*/
2343
2344 {
2345
2346 PLXT_SIGNAL_INFO Info;
2347 int WaitCount;
2348
2349 Info = LxtSignalFindThreadInfo();
2350 if (Info == NULL)
2351 {
2352 goto ErrorExit;
2353 }
2354
2355 //
2356 // N.B. It would be possible to implement this function using sigsuspend
2357 // but only after signal blocking is implemented. In order to avoid
2358 // a race where sigsuspend might hang if the signal arrives before
2359 // the call, the relevant signal should be blocked before doing the
2360 // operation that generates the signal, then call sigsuspend with a
2361 // mask that unblocks the signal.
2362 //
2363
2364 for (WaitCount = 0; (WaitCount < SIGNAL_WAIT_COUNT) && (Info->SignalCount == 0); WaitCount += 1)
2365 {
2366
2367 usleep(SIGNAL_WAIT_TIMEOUT_US);
2368 }
2369
2370 ErrorExit:
2371 return;
2372 }
2373
2374 int LxtSignalWaitBlocked(int Signal, pid_t FromPid, int TimeoutSeconds)
2375
2376 /*++
2377
2378 Routine Description:
2379
2380 This routine waits for a specific blocked signal.
2381
2382 Arguments:
2383
2384 Signal - Supplies the signal number.
2385
2386 FromPid - Supplies the expected origin of the signal.
2387
2388 TimeoutSeconds - Supplies the timeout, in seconds.
2389
2390 Return Value:
2391
2392 Returns 0 on success, -1 on failure.
2393
2394 --*/
2395
2396 {
2397
2398 int ReceivedSignal;
2399 int Result;
2400 siginfo_t SignalInfo;
2401 sigset_t Signals;
2402 struct timespec Timeout;
2403
2404 sigemptyset(&Signals);
2405 sigaddset(&Signals, Signal);
2406 Timeout.tv_sec = TimeoutSeconds;
2407 Timeout.tv_nsec = 0;
2408 LxtCheckErrno(ReceivedSignal = LxtSignalTimedWait(&Signals, &SignalInfo, &Timeout));
2409
2410 LxtCheckEqual(Signal, ReceivedSignal, "%d");
2411 LxtCheckEqual(SignalInfo.si_pid, FromPid, "%d");
2412
2413 ErrorExit:
2414 return Result;
2415 }
2416
2417 int LxtSocketPairClose(PLXT_SOCKET_PAIR SocketPair)
2418
2419 /*++
2420
2421 Routine Description:
2422
2423 This routine closes a socket pair.
2424
2425 Arguments:
2426
2427 SocketPair - Supplies a pointer to the socket pair.
2428
2429 Return Value:
2430
2431 0 on success, -1 on failure.
2432
2433 --*/
2434
2435 {
2436
2437 int Result;
2438
2439 LxtCheckResult(LxtSocketPairCloseChild(SocketPair));
2440 LxtCheckResult(LxtSocketPairCloseParent(SocketPair));
2441
2442 ErrorExit:
2443 return Result;
2444 }
2445
2446 int LxtSocketPairCloseChild(PLXT_SOCKET_PAIR SocketPair)
2447
2448 /*++
2449
2450 Routine Description:
2451
2452 This routine closes the child socket of a socket pair.
2453
2454 Arguments:
2455
2456 SocketPair - Supplies a pointer to the socket pair.
2457
2458 Return Value:
2459
2460 0 on success, -1 on failure.
2461
2462 --*/
2463
2464 {
2465
2466 int Result;
2467
2468 if (SocketPair->Child != 0)
2469 {
2470 LxtCheckErrnoZeroSuccess(close(SocketPair->Child));
2471 SocketPair->Child = 0;
2472 }
2473
2474 Result = LXT_RESULT_SUCCESS;
2475
2476 ErrorExit:
2477 return Result;
2478 }
2479
2480 int LxtSocketPairCloseParent(PLXT_SOCKET_PAIR SocketPair)
2481
2482 /*++
2483
2484 Routine Description:
2485
2486 This routine closes the parent socket of a socket pair.
2487
2488 Arguments:
2489
2490 SocketPair - Supplies a pointer to the socket pair.
2491
2492 Return Value:
2493
2494 0 on success, -1 on failure.
2495
2496 --*/
2497
2498 {
2499
2500 int Result;
2501
2502 if (SocketPair->Parent != 0)
2503 {
2504 LxtCheckErrnoZeroSuccess(close(SocketPair->Parent));
2505 SocketPair->Parent = 0;
2506 }
2507
2508 Result = LXT_RESULT_SUCCESS;
2509
2510 ErrorExit:
2511 return Result;
2512 }
2513
2514 int LxtSocketPairCreate(PLXT_SOCKET_PAIR SocketPair)
2515
2516 /*++
2517
2518 Routine Description:
2519
2520 This routine creates a socket pair.
2521
2522 Arguments:
2523
2524 SocketPair - Supplies a pointer to the socket pair.
2525
2526 Return Value:
2527
2528 0 on success, -1 on failure.
2529
2530 --*/
2531
2532 {
2533
2534 int Result;
2535
2536 memset(SocketPair, 0, sizeof(*SocketPair));
2537 LxtCheckErrnoZeroSuccess(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, (int*)SocketPair));
2538
2539 ErrorExit:
2540 return Result;
2541 }
2542
2543 int LxtWaitPidPoll(pid_t ChildPid, int ExpectedWaitStatus)
2544
2545 /*++
2546
2547 Routine Description:
2548
2549 This routine waits until the specified child exits by polling its wait
2550 status repeatedly.
2551
2552 Arguments:
2553
2554 ChildPid - Supplies the thread group ID of the child to wait on.
2555
2556 ExpectedWaitStatus - Supplies the expected value of the child's status.
2557
2558 Return Value:
2559
2560 Returns 0 on success, -1 on failure.
2561
2562 --*/
2563
2564 {
2565
2566 return LxtWaitPidPollOptions(ChildPid, ExpectedWaitStatus, 0, LXT_WAITPID_DEFAULT_TIMEOUT);
2567 }
2568
2569 int LxtWaitPidPollOptions(pid_t ChildPid, int ExpectedWaitStatus, int Options, int TimeoutSeconds)
2570
2571 /*++
2572
2573 Routine Description:
2574
2575 This routine waits until the specified child exits by polling its wait
2576 status repeatedly.
2577
2578 Arguments:
2579
2580 ChildPid - Supplies the thread group ID of the child to wait on.
2581
2582 ExpectedWaitStatus - Supplies the expected value of the child's status.
2583
2584 Options - Supplies wait options to pass to waitpid.
2585
2586 TimeoutSeconds - Supplies the number of seconds to wait for the child.
2587
2588 Return Value:
2589
2590 Returns 0 on success, -1 on failure.
2591
2592 --*/
2593
2594 {
2595
2596 int SecondWaitPidStatus;
2597 int Result;
2598 int WaitCount;
2599 int WaitCountTotal;
2600 int WaitPidResult;
2601 int WaitPidStatus;
2602
2603 //
2604 // Only WNOHANG is supported right now, so poll for the result and check the
2605 // status.
2606 //
2607
2608 Options |= WNOHANG;
2609 WaitCountTotal = (TimeoutSeconds * 1000000) / LXT_WAITPID_WAIT_TIMEOUT_US;
2610 for (WaitCount = 0; WaitCount < WaitCountTotal; ++WaitCount)
2611 {
2612 LxtCheckErrno((WaitPidResult = waitpid(ChildPid, &WaitPidStatus, Options)));
2613
2614 if (WaitPidResult != 0)
2615 {
2616 if ((WaitPidStatus & 0x80000000) != 0)
2617 {
2618 Result = LXT_RESULT_FAILURE;
2619 LxtLogError("Unexpected high bit: %x - %x", WaitPidStatus, ExpectedWaitStatus);
2620
2621 goto ErrorExit;
2622 }
2623
2624 if (WaitPidStatus != ExpectedWaitStatus)
2625 {
2626 Result = LXT_RESULT_FAILURE;
2627 LxtLogError("Unexpected status: %x != %x", WaitPidStatus, ExpectedWaitStatus);
2628
2629 goto ErrorExit;
2630 }
2631
2632 if (WIFEXITED(WaitPidStatus) != 0)
2633 {
2634 LxtCheckErrnoFailure(waitpid(ChildPid, &SecondWaitPidStatus, WNOHANG), ECHILD);
2635 }
2636
2637 Result = WaitPidResult;
2638 break;
2639 }
2640
2641 usleep(LXT_WAITPID_WAIT_TIMEOUT_US);
2642 }
2643
2644 if (WaitCount == WaitCountTotal)
2645 {
2646 Result = LXT_RESULT_FAILURE;
2647 LxtLogError("Failed to receive status %d from child {:%d:}", ExpectedWaitStatus, ChildPid);
2648
2649 goto ErrorExit;
2650 }
2651
2652 ErrorExit:
2653 return Result;
2654 }
2655
2656 int LxtClose(int FileDescriptor)
2657
2658 /*++
2659 --*/
2660
2661 {
2662 int Result;
2663
2664 LxtCheckErrnoZeroSuccess(close(FileDescriptor));
2665
2666 ErrorExit:
2667 return Result;
2668 }
2669
2670 int LxtMunmap(void* Address, size_t Length)
2671
2672 /*++
2673 --*/
2674
2675 {
2676 int Result;
2677
2678 LxtCheckErrno(munmap(Address, Length));
2679
2680 ErrorExit:
2681 return Result;
2682 }
2683
2684 int LxtWslVersion(void)
2685
2686 /*++
2687
2688 Description:
2689
2690 This routine determines whether the tests are running in WSL1 or 2.
2691
2692 Arguments:
2693
2694 None.
2695
2696 Return Value:
2697
2698 The WSL version number, 1 or 2, or 0 if an error occurred.
2699
2700 --*/
2701
2702 {
2703
2704 int Result;
2705 struct utsname UnameBuffer;
2706
2707 if (g_WslVersion == 0)
2708 {
2709 memset(&UnameBuffer, 0, sizeof(UnameBuffer));
2710 LxtCheckErrno(uname(&UnameBuffer));
2711 if (strstr(UnameBuffer.release, "Microsoft") == NULL)
2712 {
2713 g_WslVersion = 2;
2714 }
2715 else
2716 {
2717 g_WslVersion = 1;
2718 }
2719 }
2720
2721 ErrorExit:
2722 return g_WslVersion;
2723 }